View Javadoc

1   package com.bradmcevoy.http;
2   
3   import com.bradmcevoy.common.Path;
4   import com.bradmcevoy.http.AuthenticationService.AuthStatus;
5   import com.bradmcevoy.http.Request.Method;
6   import com.bradmcevoy.http.http11.Http11ResponseHandler;
7   import com.bradmcevoy.http.quota.StorageChecker;
8   import com.bradmcevoy.http.quota.StorageChecker.StorageErrorReason;
9   import java.util.List;
10  import org.slf4j.Logger;
11  import org.slf4j.LoggerFactory;
12  
13  /**
14   *
15   * @author brad
16   */
17  public class HandlerHelper {
18  
19      private final static Logger log = LoggerFactory.getLogger( HandlerHelper.class );
20      private AuthenticationService authenticationService;
21      private final List<StorageChecker> storageCheckers;
22  
23      private boolean enableExpectContinue = true;
24  
25      public HandlerHelper( AuthenticationService authenticationService, List<StorageChecker> storageCheckers ) {
26          this.authenticationService = authenticationService;
27          this.storageCheckers = storageCheckers;
28      }
29  
30      /**
31       * Checks the expect header, and responds if necessary
32       *
33       * @param resource
34       * @param request
35       * @param response
36       * @return - true if the expect header is ok. ie process normally. false means that we
37       * have sent a CONTINUE status and processing should stop until the request body is sent
38       */
39      public boolean checkExpects( Http11ResponseHandler responseHandler, Request request, Response response ) {
40          if( enableExpectContinue ) {
41              String s = request.getExpectHeader();
42              if( s != null && s.length() > 0 ) {
43                  response.setStatus( Response.Status.SC_CONTINUE );
44                  return false;
45              } else {
46                  return true;
47              }
48          } else {
49              return true;
50          }
51      }
52  
53      public AuthStatus checkAuthentication( HttpManager manager, Resource resource, Request request ) {
54          log.trace( "checkAuthentication" );
55          AuthStatus authStatus = authenticationService.authenticate( resource, request ); //handler.authenticate( auth.user, auth.password );
56          if( authStatus == null ) {
57              log.trace("checkAuthentication: null authStatus");
58              return null;
59          } else {
60              log.trace("checkAuthentication: authStatus.failed =" + authStatus.loginFailed);
61              return authStatus;
62          }
63      }
64  
65      public boolean checkAuthorisation( HttpManager manager, Resource resource, Request request ) {
66          log.trace("checkAuthorisation");
67          AuthStatus authStatus = checkAuthentication( manager, resource, request );
68          
69          // a null authStatus means that no authentication was attempted, eg an anonymous request
70          // it is up to the implementation to decide whether or not to allow anonymous access
71          // however a failed login must always be rejected
72          if( authStatus != null && authStatus.loginFailed ) {
73              log.trace("checkAuthorisation: loginFailed");
74              return false;
75          }
76          Auth auth;
77          if( authStatus != null ) {
78              log.trace("checkAuthorisation: got auth object");
79              auth = authStatus.auth;
80          } else {
81              log.trace("checkAuthorisation: authStatus is null, no authentication was attempted");
82              auth = null;
83          }
84          boolean authorised = resource.authorise( request, request.getMethod(), auth );
85          if( !authorised ) {
86              if( log.isWarnEnabled() ) {
87                  log.warn( "authorisation declined, requesting authentication: " + request.getAbsolutePath() + ". resource type: " + resource.getClass().getCanonicalName() );
88              }
89              if( auth != null ) {
90                  if( log.isTraceEnabled() ) {
91                      log.trace( "  - auth: " + auth.getUser() + " tag: " + auth.getTag() );
92                  }
93              } else {
94                  log.trace( "  - anonymous request" );
95              }
96              return false;
97          } else {
98              return true;
99          }
100     }
101 
102     public boolean doCheckRedirect( Http11ResponseHandler responseHandler, Request request, Response response, Resource resource ) {
103         String redirectUrl = resource.checkRedirect( request );
104         if( redirectUrl != null && redirectUrl.length() > 0 ) {
105             responseHandler.respondRedirect( response, request, redirectUrl );
106             return true;
107         } else {
108             return false;
109         }
110     }
111 
112     /**
113      * TODO: move to webdav
114      * 
115      * @param inRequest
116      * @param inResource
117      * @return
118      */
119     public boolean isLockedOut( Request inRequest, Resource inResource ) {
120         if( inResource == null || !( inResource instanceof LockableResource ) ) {
121             return false;
122         }
123         LockableResource lr = (LockableResource) inResource;
124         LockToken token = lr.getCurrentLock();
125         if( token != null ) {
126             Auth auth = inRequest.getAuthorization();
127             Object sUser = null;
128             if( auth != null ) sUser = auth.getUser();
129             String lockedByUser = token.info.lockedByUser;
130             if( lockedByUser == null ) {
131                 log.warn( "Resource is locked with a null user. Ignoring the lock" );
132                 return false;
133             } else if( !lockedByUser.equals( sUser ) ) {
134                 if( log.isInfoEnabled() ) {
135                     if( auth == null ) {
136                         log.trace( "lock owned by: " + lockedByUser );
137                     } else {
138                         log.trace( "lock owned by: " + lockedByUser + " not by " + auth.getUser() );
139                     }
140                 }
141                 String value = inRequest.getIfHeader();
142                 if( value != null ) {
143                     if( value.contains( "opaquelocktoken:" + token.tokenId + ">" ) ) {
144                         log.trace( "Request contains valid token so operation is permitted" );
145                         return false;
146                     }
147                 }
148                 return true;
149             }
150         }
151         return false;
152     }
153 
154     public boolean missingLock( Request inRequest, Resource inParentcol ) {
155         //make sure we are not requiring a lock
156         String value = inRequest.getIfHeader();
157         if( value != null ) {
158             if( value.contains( "(<DAV:no-lock>)" ) ) {
159                 log.info( "Contained valid token. so is unlocked" );
160                 return true;
161             }
162         }
163 
164         return false;
165     }
166 
167     public StorageErrorReason checkStorageOnReplace( Request request, CollectionResource parentCol, Resource replaced, String host ) {
168         for( StorageChecker sc : storageCheckers ) {
169             StorageErrorReason res = sc.checkStorageOnReplace( request, parentCol, replaced, host );
170             if( res != null ) {
171                 log.warn( "insufficient storage reason: " + res + " reported by: " + sc.getClass() );
172                 return res;
173             }
174         }
175         return null;
176     }
177 
178     public StorageErrorReason checkStorageOnAdd( Request request, CollectionResource nearestParent, Path parentPath, String host ) {
179         for( StorageChecker sc : storageCheckers ) {
180             StorageErrorReason res = sc.checkStorageOnAdd( request, nearestParent, parentPath, host );
181             if( res != null ) {
182                 log.warn( "insufficient storage reason: " + res + " reported by: " + sc.getClass() );
183                 return res;
184             }
185         }
186         return null;
187     }
188 
189     /**
190      * Returns true to indicate that the given resource MUST NOT handle the 
191      * given method.
192      * 
193      * A return value of false indicates that it might.
194      * 
195      * @param r - the resource to check
196      * @param m - the HTTP request method
197      * @return - true to indicate the resource must not handle method m
198      */
199     public boolean isNotCompatible( Resource r, Method m ) {
200         if( r instanceof ConditionalCompatibleResource ) {
201             ConditionalCompatibleResource ccr = (ConditionalCompatibleResource) r;
202             return !ccr.isCompatible( m );
203         }
204         return false;
205     }
206 
207     public boolean isEnableExpectContinue() {
208         return enableExpectContinue;
209     }
210 
211     public void setEnableExpectContinue( boolean enableExpectContinue ) {
212         this.enableExpectContinue = enableExpectContinue;
213     }
214 }