View Javadoc

1   /*
2    * $Id: ServletRedirectResult.java 501746 2007-01-31 06:22:43Z mrdon $
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;
22  
23  import javax.servlet.http.HttpServletRequest;
24  import javax.servlet.http.HttpServletResponse;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.struts2.ServletActionContext;
29  import org.apache.struts2.dispatcher.mapper.ActionMapper;
30  import org.apache.struts2.dispatcher.mapper.ActionMapping;
31  
32  import com.opensymphony.xwork2.ActionContext;
33  import com.opensymphony.xwork2.ActionInvocation;
34  import com.opensymphony.xwork2.inject.Inject;
35  
36  
37  /***
38   * <!-- START SNIPPET: description -->
39   *
40   * Calls the {@link HttpServletResponse#sendRedirect(String) sendRedirect}
41   * method to the location specified. The response is told to redirect the
42   * browser to the specified location (a new request from the client). The
43   * consequence of doing this means that the action (action instance, action
44   * errors, field errors, etc) that was just executed is lost and no longer
45   * available. This is because actions are built on a single-thread model. The
46   * only way to pass data is through the session or with web parameters
47   * (url?name=value) which can be OGNL expressions.
48   *
49   * <!-- END SNIPPET: description -->
50   * <p/>
51   * <b>This result type takes the following parameters:</b>
52   *
53   * <!-- START SNIPPET: params -->
54   *
55   * <ul>
56   *
57   * <li><b>location (default)</b> - the location to go to after execution.</li>
58   *
59   * <li><b>parse</b> - true by default. If set to false, the location param will
60   * not be parsed for Ognl expressions.</li>
61   *
62   * </ul>
63   *
64   * <p>
65   * This result follows the same rules from {@link StrutsResultSupport}.
66   * </p>
67   *
68   * <!-- END SNIPPET: params -->
69   *
70   * <b>Example:</b>
71   *
72   * <pre><!-- START SNIPPET: example -->
73   * &lt;result name="success" type="redirect"&gt;
74   *   &lt;param name="location"&gt;foo.jsp&lt;/param&gt;
75   *   &lt;param name="parse"&gt;false&lt;/param&gt;
76   * &lt;/result&gt;
77   * <!-- END SNIPPET: example --></pre>
78   *
79   */
80  public class ServletRedirectResult extends StrutsResultSupport {
81  
82      private static final long serialVersionUID = 6316947346435301270L;
83  
84      private static final Log log = LogFactory.getLog(ServletRedirectResult.class);
85  
86      protected boolean prependServletContext = true;
87  
88      protected ActionMapper actionMapper;
89  
90      public ServletRedirectResult() {
91          super();
92      }
93  
94      public ServletRedirectResult(String location) {
95          super(location);
96      }
97      
98      @Inject
99      public void setActionMapper(ActionMapper mapper) {
100         this.actionMapper = mapper;
101     }
102 
103     /***
104      * Sets whether or not to prepend the servlet context path to the redirected URL.
105      *
106      * @param prependServletContext <tt>true</tt> to prepend the location with the servlet context path,
107      *                              <tt>false</tt> otherwise.
108      */
109     public void setPrependServletContext(boolean prependServletContext) {
110         this.prependServletContext = prependServletContext;
111     }
112 
113     /***
114      * Redirects to the location specified by calling {@link HttpServletResponse#sendRedirect(String)}.
115      *
116      * @param finalLocation the location to redirect to.
117      * @param invocation    an encapsulation of the action execution state.
118      * @throws Exception if an error occurs when redirecting.
119      */
120     protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
121         ActionContext ctx = invocation.getInvocationContext();
122         HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);
123         HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
124 
125         if (isPathUrl(finalLocation)) {
126             if (!finalLocation.startsWith("/")) {
127                 ActionMapping mapping = actionMapper.getMapping(
128                         request, Dispatcher.getInstance().getConfigurationManager()); 
129                 String namespace = null;
130                 if (mapping != null) {
131                     namespace = mapping.getNamespace();
132                 }
133 
134                 if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) {
135                     finalLocation = namespace + "/" + finalLocation;
136                 } else {
137                     finalLocation = "/" + finalLocation;
138                 }
139             }
140 
141             // if the URL's are relative to the servlet context, append the servlet context path
142             if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) {
143                 finalLocation = request.getContextPath() + finalLocation;
144             }
145 
146             finalLocation = response.encodeRedirectURL(finalLocation);
147         }
148 
149         if (log.isDebugEnabled()) {
150             log.debug("Redirecting to finalLocation " + finalLocation);
151         }
152 
153         response.sendRedirect(finalLocation);
154     }
155 
156     private static boolean isPathUrl(String url) {
157         // filter out "http:", "https:", "mailto:", "file:", "ftp:"
158         // since the only valid places for : in URL's is before the path specification
159         // either before the port, or after the protocol
160         return (url.indexOf(':') == -1);
161     }
162 }