View Javadoc

1   /*
2    * $Id: TokenSessionStoreInterceptor.java 454565 2006-10-10 00:02:56Z jmitchell $
3    *
4    * Copyright 2006 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.struts2.interceptor;
19  
20  import java.util.Map;
21  
22  import javax.servlet.http.HttpServletRequest;
23  
24  import org.apache.struts2.ServletActionContext;
25  import org.apache.struts2.util.InvocationSessionStore;
26  import org.apache.struts2.util.TokenHelper;
27  
28  import com.opensymphony.xwork2.ActionContext;
29  import com.opensymphony.xwork2.ActionInvocation;
30  import com.opensymphony.xwork2.Result;
31  import com.opensymphony.xwork2.util.ValueStack;
32  
33  
34  /***
35   * <!-- START SNIPPET: description -->
36   *
37   * This interceptor builds off of the {@link TokenInterceptor}, providing advanced logic for handling invalid tokens.
38   * Unlike the normal token interceptor, this interceptor will attempt to provide intelligent fail-over in the event of
39   * multiple requests using the same session. That is, it will block subsequent requests until the first request is
40   * complete, and then instead of returning the <i>invalid.token</i> code, it will attempt to display the same response
41   * that the original, valid action invocation would have displayed if no multiple requests were submitted in the first
42   * place.
43   * 
44   * <p/>
45   * 
46   * <b>NOTE:</b> As this method extends off MethodFilterInterceptor, it is capable of
47   * deciding if it is applicable only to selective methods in the action class. See
48   * <code>MethodFilterInterceptor</code> for more info.
49   *
50   * <!-- END SNIPPET: description -->
51   *
52   * <p/> <u>Interceptor parameters:</u>
53   *
54   * <!-- START SNIPPET: parameters -->
55   *
56   * <ul>
57   *
58   * <li>None</li>
59   *
60   * </ul>
61   *
62   * <!-- END SNIPPET: parameters -->
63   *
64   * <p/> <u>Extending the interceptor:</u>
65   *
66   * <p/>
67   *
68   * <!-- START SNIPPET: extending -->
69   *
70   * There are no known extension points for this interceptor.
71   *
72   * <!-- END SNIPPET: extending -->
73   *
74   * <p/> <u>Example code:</u>
75   *
76   * <pre>
77   * <!-- START SNIPPET: example -->
78   * 
79   * &lt;action name="someAction" class="com.examples.SomeAction"&gt;
80   *     &lt;interceptor-ref name="token-session/&gt;
81   *     &lt;interceptor-ref name="basicStack"/&gt;
82   *     &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
83   * &lt;/action&gt;
84   * 
85   * &lt;-- In this case, myMethod of the action class will not 
86   *        get checked for invalidity of token --&gt;
87   * &lt;action name="someAction" class="com.examples.SomeAction"&gt;
88   *     &lt;interceptor-ref name="token-session&gt;
89   *         &lt;param name="excludeMethods"&gt;myMethod&lt;/param&gt;
90   *     &lt;/interceptor-ref name="token-session&gt;
91   *     &lt;interceptor-ref name="basicStack"/&gt;
92   *     &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
93   * &lt;/action&gt;
94   * 
95   * <!-- END SNIPPET: example -->
96   * </pre>
97   *
98   */
99  public class TokenSessionStoreInterceptor extends TokenInterceptor {
100 	
101 	private static final long serialVersionUID = -9032347965469098195L;
102 
103 	/* (non-Javadoc)
104 	 * @see org.apache.struts2.interceptor.TokenInterceptor#handleInvalidToken(com.opensymphony.xwork2.ActionInvocation)
105 	 */
106 	protected String handleInvalidToken(ActionInvocation invocation) throws Exception {
107         ActionContext ac = invocation.getInvocationContext();
108 
109         HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
110         String tokenName = TokenHelper.getTokenName();
111         String token = TokenHelper.getToken(tokenName);
112 
113         Map params = ac.getParameters();
114         params.remove(tokenName);
115         params.remove(TokenHelper.TOKEN_NAME_FIELD);
116 
117         if ((tokenName != null) && (token != null)) {
118             ActionInvocation savedInvocation = InvocationSessionStore.loadInvocation(tokenName, token);
119 
120             if (savedInvocation != null) {
121                 // set the valuestack to the request scope
122                 ValueStack stack = savedInvocation.getStack();
123                 request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
124 
125                 Result result = savedInvocation.getResult();
126 
127                 if ((result != null) && (savedInvocation.getProxy().getExecuteResult())) {
128                     result.execute(savedInvocation);
129                 }
130 
131                 // turn off execution of this invocations result
132                 invocation.getProxy().setExecuteResult(false);
133 
134                 return savedInvocation.getResultCode();
135             }
136         }
137 
138         return INVALID_TOKEN_CODE;
139     }
140 
141     /* (non-Javadoc)
142      * @see org.apache.struts2.interceptor.TokenInterceptor#handleValidToken(com.opensymphony.xwork2.ActionInvocation)
143      */
144     protected String handleValidToken(ActionInvocation invocation) throws Exception {
145         // we know the token name and token must be there
146         String key = TokenHelper.getTokenName();
147         String token = TokenHelper.getToken(key);
148         InvocationSessionStore.storeInvocation(key, token, invocation);
149 
150         return invocation.invoke();
151     }
152 }