View Javadoc

1   /*
2    * $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts2.dispatcher.ng;
22  
23  import org.apache.struts2.dispatcher.Dispatcher;
24  import org.apache.struts2.dispatcher.mapper.ActionMapping;
25  import org.apache.struts2.dispatcher.mapper.ActionMapper;
26  import org.apache.struts2.StrutsException;
27  
28  import javax.servlet.ServletException;
29  import javax.servlet.ServletContext;
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  
33  import com.opensymphony.xwork2.ActionContext;
34  import com.opensymphony.xwork2.util.ValueStack;
35  import com.opensymphony.xwork2.util.ValueStackFactory;
36  import com.opensymphony.xwork2.util.logging.Logger;
37  import com.opensymphony.xwork2.util.logging.LoggerFactory;
38  
39  import java.io.IOException;
40  import java.util.HashMap;
41  
42  /***
43   * Contains preparation operations for a request before execution
44   */
45  public class PrepareOperations {
46  
47      private ServletContext servletContext;
48      private Dispatcher dispatcher;
49      private static final String STRUTS_ACTION_MAPPING_KEY = "struts.actionMapping";
50      public static final String CLEANUP_RECURSION_COUNTER = "__cleanup_recursion_counter";
51      private Logger log = LoggerFactory.getLogger(PrepareOperations.class);
52  
53      public PrepareOperations(ServletContext servletContext, Dispatcher dispatcher) {
54          this.dispatcher = dispatcher;
55          this.servletContext = servletContext;
56      }
57  
58      /***
59       * Creates the action context and initializes the thread local
60       */
61      public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {
62          ActionContext ctx;
63          Integer counter = 1;
64          Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);
65          if (oldCounter != null) {
66              counter = oldCounter + 1;
67          }
68          
69          ActionContext oldContext = ActionContext.getContext();
70          if (oldContext != null) {
71              // detected existing context, so we are probably in a forward
72              ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap()));
73          } else {
74              ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
75              stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext));
76              ctx = new ActionContext(stack.getContext());
77          }
78          request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);
79          ActionContext.setContext(ctx);
80          return ctx;
81      }
82  
83      /***
84       * Cleans up a request of thread locals
85       */
86      public void cleanupRequest(HttpServletRequest request) {
87          Integer counterVal = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);
88          if (counterVal != null) {
89              counterVal -= 1;
90              request.setAttribute(CLEANUP_RECURSION_COUNTER, counterVal);
91              if (counterVal > 0 ) {
92                  if (log.isDebugEnabled()) {
93                      log.debug("skipping cleanup counter="+counterVal);
94                  }
95                  return;
96              }
97          }
98  
99          // always clean up the thread request, even if an action hasn't been executed
100         ActionContext.setContext(null);
101         Dispatcher.setInstance(null);
102     }
103 
104     /***
105      * Assigns the dispatcher to the dispatcher thread local
106      */
107     public void assignDispatcherToThread() {
108         Dispatcher.setInstance(dispatcher);
109     }
110 
111     /***
112      * Sets the request encoding and locale on the response
113      */
114     public void setEncodingAndLocale(HttpServletRequest request, HttpServletResponse response) {
115         dispatcher.prepare(request, response);
116     }
117 
118     /***
119      * Wraps the request with the Struts wrapper that handles multipart requests better
120      * @return The new request, if there is one
121      * @throws ServletException
122      */
123     public HttpServletRequest wrapRequest(HttpServletRequest oldRequest) throws ServletException {
124         HttpServletRequest request = oldRequest;
125         try {
126             // Wrap request first, just in case it is multipart/form-data
127             // parameters might not be accessible through before encoding (ww-1278)
128             request = dispatcher.wrapRequest(request, servletContext);
129         } catch (IOException e) {
130             String message = "Could not wrap servlet request with MultipartRequestWrapper!";
131             throw new ServletException(message, e);
132         }
133         return request;
134     }
135 
136     /***
137      * Finds and optionally creates an {@link ActionMapping}.  It first looks in the current request to see if one
138      * has already been found, otherwise, it creates it and stores it in the request.  No mapping will be created in the
139      * case of static resource requests or unidentifiable requests for other servlets, for example.
140      */
141     public ActionMapping findActionMapping(HttpServletRequest request, HttpServletResponse response) {
142         ActionMapping mapping = (ActionMapping) request.getAttribute(STRUTS_ACTION_MAPPING_KEY);
143         if (mapping == null) {
144             try {
145                 mapping = dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(request, dispatcher.getConfigurationManager());
146                 if (mapping != null) {
147                     request.setAttribute(STRUTS_ACTION_MAPPING_KEY, mapping);
148                 }
149             } catch (Exception ex) {
150                 dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
151             }
152         }
153 
154         return mapping;
155     }
156 
157     /***
158      * Cleans up the dispatcher instance
159      */
160     public void cleanupDispatcher() {
161         if (dispatcher == null) {
162             throw new StrutsException("something is seriously wrong, Dispatcher is not initialized (null) ");
163         } else {
164             try {
165                 dispatcher.cleanup();
166             } finally {
167                 ActionContext.setContext(null);
168             }
169         }
170     }
171 }