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 }