001: /*
002: * $Id: TokenSessionStoreInterceptor.java 517433 2007-03-12 22:34:58Z husted $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts2.interceptor;
022:
023: import java.util.Map;
024:
025: import javax.servlet.http.HttpServletRequest;
026: import javax.servlet.http.HttpServletResponse;
027:
028: import org.apache.struts2.ServletActionContext;
029: import org.apache.struts2.util.InvocationSessionStore;
030: import org.apache.struts2.util.TokenHelper;
031:
032: import com.opensymphony.xwork2.ActionContext;
033: import com.opensymphony.xwork2.ActionInvocation;
034: import com.opensymphony.xwork2.Result;
035: import com.opensymphony.xwork2.util.ValueStack;
036:
037: /**
038: * <!-- START SNIPPET: description -->
039: *
040: * This interceptor builds off of the {@link TokenInterceptor}, providing advanced logic for handling invalid tokens.
041: * Unlike the normal token interceptor, this interceptor will attempt to provide intelligent fail-over in the event of
042: * multiple requests using the same session. That is, it will block subsequent requests until the first request is
043: * complete, and then instead of returning the <i>invalid.token</i> code, it will attempt to display the same response
044: * that the original, valid action invocation would have displayed if no multiple requests were submitted in the first
045: * place.
046: *
047: * <p/>
048: *
049: * <b>NOTE:</b> As this method extends off MethodFilterInterceptor, it is capable of
050: * deciding if it is applicable only to selective methods in the action class. See
051: * <code>MethodFilterInterceptor</code> for more info.
052: *
053: * <!-- END SNIPPET: description -->
054: *
055: * <p/> <u>Interceptor parameters:</u>
056: *
057: * <!-- START SNIPPET: parameters -->
058: *
059: * <ul>
060: *
061: * <li>None</li>
062: *
063: * </ul>
064: *
065: * <!-- END SNIPPET: parameters -->
066: *
067: * <p/> <u>Extending the interceptor:</u>
068: *
069: * <p/>
070: *
071: * <!-- START SNIPPET: extending -->
072: *
073: * There are no known extension points for this interceptor.
074: *
075: * <!-- END SNIPPET: extending -->
076: *
077: * <p/> <u>Example code:</u>
078: *
079: * <pre>
080: * <!-- START SNIPPET: example -->
081: *
082: * <action name="someAction" class="com.examples.SomeAction">
083: * <interceptor-ref name="token-session/>
084: * <interceptor-ref name="basicStack"/>
085: * <result name="success">good_result.ftl</result>
086: * </action>
087: *
088: * <-- In this case, myMethod of the action class will not
089: * get checked for invalidity of token -->
090: * <action name="someAction" class="com.examples.SomeAction">
091: * <interceptor-ref name="token-session>
092: * <param name="excludeMethods">myMethod</param>
093: * </interceptor-ref name="token-session>
094: * <interceptor-ref name="basicStack"/>
095: * <result name="success">good_result.ftl</result>
096: * </action>
097: *
098: * <!-- END SNIPPET: example -->
099: * </pre>
100: *
101: */
102: public class TokenSessionStoreInterceptor extends TokenInterceptor {
103:
104: private static final long serialVersionUID = -9032347965469098195L;
105:
106: /* (non-Javadoc)
107: * @see org.apache.struts2.interceptor.TokenInterceptor#handleInvalidToken(com.opensymphony.xwork2.ActionInvocation)
108: */
109: protected String handleInvalidToken(ActionInvocation invocation)
110: throws Exception {
111: ActionContext ac = invocation.getInvocationContext();
112:
113: HttpServletRequest request = (HttpServletRequest) ac
114: .get(ServletActionContext.HTTP_REQUEST);
115: HttpServletResponse response = (HttpServletResponse) ac
116: .get(ServletActionContext.HTTP_RESPONSE);
117: String tokenName = TokenHelper.getTokenName();
118: String token = TokenHelper.getToken(tokenName);
119:
120: Map params = ac.getParameters();
121: params.remove(tokenName);
122: params.remove(TokenHelper.TOKEN_NAME_FIELD);
123:
124: if ((tokenName != null) && (token != null)) {
125: ActionInvocation savedInvocation = InvocationSessionStore
126: .loadInvocation(tokenName, token);
127:
128: if (savedInvocation != null) {
129: // set the valuestack to the request scope
130: ValueStack stack = savedInvocation.getStack();
131: Map context = stack.getContext();
132: request.setAttribute(
133: ServletActionContext.STRUTS_VALUESTACK_KEY,
134: stack);
135:
136: ActionContext savedContext = savedInvocation
137: .getInvocationContext();
138: savedContext.getContextMap().put(
139: ServletActionContext.HTTP_REQUEST, request);
140: savedContext.getContextMap().put(
141: ServletActionContext.HTTP_RESPONSE, response);
142: Result result = savedInvocation.getResult();
143:
144: if ((result != null)
145: && (savedInvocation.getProxy()
146: .getExecuteResult())) {
147: synchronized (context) {
148: result.execute(savedInvocation);
149: }
150: }
151:
152: // turn off execution of this invocations result
153: invocation.getProxy().setExecuteResult(false);
154:
155: return savedInvocation.getResultCode();
156: }
157: }
158:
159: return INVALID_TOKEN_CODE;
160: }
161:
162: /* (non-Javadoc)
163: * @see org.apache.struts2.interceptor.TokenInterceptor#handleValidToken(com.opensymphony.xwork2.ActionInvocation)
164: */
165: protected String handleValidToken(ActionInvocation invocation)
166: throws Exception {
167: // we know the token name and token must be there
168: String key = TokenHelper.getTokenName();
169: String token = TokenHelper.getToken(key);
170: InvocationSessionStore.storeInvocation(key, token, invocation);
171:
172: return invocation.invoke();
173: }
174: }
|