View Javadoc

1   /***
2    *
3    * Copyright 2003-2005 Core Developers Network Ltd.
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.codehaus.wadi.core.contextualiser;
18  
19  import java.util.regex.Pattern;
20  
21  import javax.servlet.http.HttpServletRequest;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.codehaus.wadi.core.motable.Immoter;
26  import org.codehaus.wadi.web.HttpInvocationContext;
27  import org.codehaus.wadi.web.impl.BasicHttpInvocationContext;
28  import org.codehaus.wadi.web.impl.WebInvocation;
29  
30  //N.B.
31  //Ultimately this should support pluggable and combinable 'Tests' - i.e. URIPatternTest
32  //MethodPatternTest & AndTest...
33  
34  /***
35   * A Contextualiser that will intercept requests that can be shown to be stateless
36   * and run them in a generic stateless Context immediately, without the overhead of
37   * locating the (possibly remote) relevant Context.
38   *
39   * Logically, this Contextualiser should sit at the top of the stack, preventing
40   * unecessary cycles being spent locating state that will not actually be consumed
41   * by the incoming request. Actually, taking into account the expense of performing
42   * this check, vs. the expense of checking locally for the session, or locating a
43   * remote session, the sensible place to deploy this Contextualiser may be at the
44   * boundary between local and remote Contextualisers.
45   *
46   * If you are caching static content agressively you may not need this Contextualiser.
47   *
48   * @author <a href="mailto:jules@coredevelopers.net">Jules Gosnell</a>
49   * @version $Revision: 2287 $
50   */
51  public class StatelessContextualiser extends AbstractDelegatingContextualiser {
52  
53  	protected final Pattern _methods; // =Pattern.compile("GET|POST", Pattern.CASE_INSENSITIVE); // TODO - |HEAD|PUT|DELETE ?
54  	protected final boolean _methodFlag; //true
55  	protected final Pattern _uris; //=Pattern.compile(".*//.(JPG|JPEG|GIF|PNG|ICO|HTML|HTM)", Pattern.CASE_INSENSITIVE); // TODO - CSS, ...?
56  	protected final boolean _uriFlag; // false
57  	protected final Log _lockLog=LogFactory.getLog("org.codehaus.wadi.LOCKS");
58  
59  	/***
60  	 * @param next - The next Contextualiser in the stack
61  	 * @param methods - Pattern used to match HTTP method names (null will match nothing)
62  	 * @param methodFlag - Does this Pattern match stateful (true) or stateless (false) HTTP methods
63  	 * @param uris - Pattern used to match URIs (null will match nothing)
64  	 * @param uriFlag - Does this Pattern match stateful (true) or stateless (false) URIs
65  	 */
66  	public StatelessContextualiser(Contextualiser next, Pattern methods, boolean methodFlag, Pattern uris, boolean uriFlag) {
67  		super(next);
68  		_methods=methods;
69  		_methodFlag=methodFlag;
70  		_uris=uris;
71  		_uriFlag=uriFlag;
72  	}
73  
74  	public boolean contextualise(Invocation invocation, String key, Immoter immoter, boolean exclusiveOnly) throws InvocationException {
75  		WebInvocation webInvocation = (WebInvocation) invocation;
76  		HttpServletRequest hreq = webInvocation.getHreq();
77  		if (hreq==null || isStateful(hreq)) {
78  			// we cannot optimise...
79  			return next.contextualise(invocation, key, immoter, exclusiveOnly);
80  		} else {
81  			// wrap the request so that session is inaccessible and process here...
82              HttpInvocationContext invocationContext = new BasicHttpInvocationContext(invocation);
83  			invocation.invoke(invocationContext);
84  			return true;
85  		}
86  	}
87  
88  	/***
89  	 * We know request is stateful - if, either Pattern matches
90  	 * stateFULL requests AND match succeeded, or Pattern matches
91  	 * stateLESS requests AND matched failed
92  	 *
93  	 * @param hreq
94  	 * @return - whether, or not, the request must be assumed stateful
95  	 */
96  	public boolean isStateful(HttpServletRequest hreq) {
97  		// TODO - should the order of matching be configurable ?
98  		boolean matched;
99  
100 		// can we prove it is stateless ? - try first test...
101 		if (_methods!=null) {
102 			matched=(_methods.matcher(hreq.getMethod()).matches());
103 			if (matched!=_methodFlag)
104 				return false;
105 		}
106 
107 		// could still be stateful - try second test...
108 		if (_uris!=null) {
109 			matched=(_uris.matcher(hreq.getRequestURI()).matches());
110 			if (matched!=_uriFlag)
111 				return false;
112 		}
113 
114 		// we cannot eliminate the possibility that the request is stateful...
115 		return true;
116 	}
117 }