View Javadoc

    1   /*
    2    * $Id: PortletResult.java 497293 2007-01-18 03:13:27Z 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.portlet.result;
    22
    23  import java.io.IOException;
    24  import java.util.StringTokenizer;
    25
    26  import javax.portlet.ActionResponse;
    27  import javax.portlet.PortletConfig;
    28  import javax.portlet.PortletException;
    29  import javax.portlet.PortletRequestDispatcher;
    30  import javax.portlet.RenderRequest;
    31  import javax.portlet.RenderResponse;
    32  import javax.servlet.ServletContext;
    33  import javax.servlet.ServletException;
    34  import javax.servlet.http.HttpServletRequest;
    35  import javax.servlet.http.HttpServletResponse;
    36
    37  import org.apache.commons.logging.Log;
    38  import org.apache.commons.logging.LogFactory;
    39  import org.apache.struts2.ServletActionContext;
    40  import org.apache.struts2.dispatcher.StrutsResultSupport;
    41  import org.apache.struts2.portlet.PortletActionConstants;
    42  import org.apache.struts2.portlet.context.PortletActionContext;
    43
    44  import com.opensymphony.xwork2.ActionInvocation;
    45  import com.opensymphony.xwork2.util.TextUtils;
    46
    47  /***
    48   * Result type that includes a JSP to render.
    49   *
    50   */
    51  public class PortletResult extends StrutsResultSupport {
    52
    53      private static final long serialVersionUID = 434251393926178567L;
    54
    55      /***
    56       * Logger instance.
    57       */
    58      private static final Log LOG = LogFactory.getLog(PortletResult.class);
    59
    60      private String contentType = "text/html";
    61
    62      private String title;
    63
    64      public PortletResult() {
    65          super();
    66      }
    67
    68      public PortletResult(String location) {
    69          super(location);
    70      }
    71
    72      /***
    73       * Execute the result. Obtains the
    74       * {@link javax.portlet.PortletRequestDispatcher}from the
    75       * {@link PortletActionContext}and includes the JSP.
    76       *
    77       * @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)
    78       */
    79      public void doExecute(String finalLocation,
    80              ActionInvocation actionInvocation) throws Exception {
    81
    82          if (PortletActionContext.isRender()) {
    83              executeRenderResult(finalLocation);
    84          } else if (PortletActionContext.isEvent()) {
    85              executeActionResult(finalLocation, actionInvocation);
    86          } else {
    87              executeRegularServletResult(finalLocation, actionInvocation);
    88          }
    89      }
    90
    91      /***
    92       * Executes the regular servlet result.
    93       *
    94       * @param finalLocation
    95       * @param actionInvocation
    96       */
    97      private void executeRegularServletResult(String finalLocation,
    98              ActionInvocation actionInvocation) throws ServletException, IOException {
    99          ServletContext ctx = ServletActionContext.getServletContext();
    100         HttpServletRequest req = ServletActionContext.getRequest();
    101         HttpServletResponse res = ServletActionContext.getResponse();
    102         try {
    103             ctx.getRequestDispatcher(finalLocation).include(req, res);
    104         } catch (ServletException e) {
    105             LOG.error("ServletException including " + finalLocation, e);
    106             throw e;
    107         } catch (IOException e) {
    108             LOG.error("IOException while including result '" + finalLocation + "'", e);
    109             throw e;
    110         }
    111     }
    112
    113     /***
    114      * Executes the action result.
    115      *
    116      * @param finalLocation
    117      * @param invocation
    118      */
    119     protected void executeActionResult(String finalLocation,
    120             ActionInvocation invocation) {
    121         LOG.debug("Executing result in Event phase");
    122         ActionResponse res = PortletActionContext.getActionResponse();
    123         LOG.debug("Setting event render parameter: " + finalLocation);
    124         if (finalLocation.indexOf('?') != -1) {
    125             convertQueryParamsToRenderParams(res, finalLocation
    126                     .substring(finalLocation.indexOf('?') + 1));
    127             finalLocation = finalLocation.substring(0, finalLocation
    128                     .indexOf('?'));
    129         }
    130         if (finalLocation.endsWith(".action")) {
    131             // View is rendered with a view action...luckily...
    132             finalLocation = finalLocation.substring(0, finalLocation
    133                     .lastIndexOf("."));
    134             res.setRenderParameter(PortletActionConstants.ACTION_PARAM, finalLocation);
    135         } else {
    136             // View is rendered outside an action...uh oh...
    137             res.setRenderParameter(PortletActionConstants.ACTION_PARAM, "renderDirect");
    138             res.setRenderParameter("location", finalLocation);
    139         }
    140         res.setRenderParameter(PortletActionConstants.MODE_PARAM, PortletActionContext
    141                 .getRequest().getPortletMode().toString());
    142     }
    143
    144     /***
    145      * Converts the query params to render params.
    146      *
    147      * @param response
    148      * @param queryParams
    149      */
    150     protected static void convertQueryParamsToRenderParams(
    151             ActionResponse response, String queryParams) {
    152         StringTokenizer tok = new StringTokenizer(queryParams, "&");
    153         while (tok.hasMoreTokens()) {
    154             String token = tok.nextToken();
    155             String key = token.substring(0, token.indexOf('='));
    156             String value = token.substring(token.indexOf('=') + 1);
    157             response.setRenderParameter(key, value);
    158         }
    159     }
    160
    161     /***
    162      * Executes the render result.
    163      *
    164      * @param finalLocation
    165      * @throws PortletException
    166      * @throws IOException
    167      */
    168     protected void executeRenderResult(final String finalLocation) throws PortletException, IOException {
    169         LOG.debug("Executing result in Render phase");
    170         PortletConfig cfg = PortletActionContext.getPortletConfig();
    171         RenderRequest req = PortletActionContext.getRenderRequest();
    172         RenderResponse res = PortletActionContext.getRenderResponse();
    173         LOG.debug("PortletConfig: " + cfg);
    174         LOG.debug("RenderRequest: " + req);
    175         LOG.debug("RenderResponse: " + res);
    176         res.setContentType(contentType);
    177         if (TextUtils.stringSet(title)) {
    178             res.setTitle(title);
    179         }
    180         LOG.debug("Location: " + finalLocation);
    181         PortletRequestDispatcher preparator = cfg.getPortletContext()
    182                 .getNamedDispatcher("preparator");
    183         if(preparator == null) {
    184             throw new PortletException("Cannot look up 'preparator' servlet. Make sure that you" +
    185                     "have configured it correctly in the web.xml file.");
    186         }
    187         new IncludeTemplate() {
    188             protected void when(PortletException e) {
    189                 LOG.error("PortletException while dispatching to 'preparator' servlet", e);
    190             }
    191             protected void when(IOException e) {
    192                 LOG.error("IOException while dispatching to 'preparator' servlet", e);
    193             }
    194         }.include(preparator, req, res);
    195         PortletRequestDispatcher dispatcher = cfg.getPortletContext().getRequestDispatcher(finalLocation);
    196         if(dispatcher == null) {
    197             throw new PortletException("Could not locate dispatcher for '" + finalLocation + "'");
    198         }
    199         new IncludeTemplate() {
    200             protected void when(PortletException e) {
    201                 LOG.error("PortletException while dispatching to '" + finalLocation + "'");
    202             }
    203             protected void when(IOException e) {
    204                 LOG.error("IOException while dispatching to '" + finalLocation + "'");
    205             }
    206         }.include(dispatcher, req, res);
    207     }
    208
    209     /***
    210      * Sets the content type.
    211      *
    212      * @param contentType The content type to set.
    213      */
    214     public void setContentType(String contentType) {
    215         this.contentType = contentType;
    216     }
    217
    218     /***
    219      * Sets the title.
    220      *
    221      * @param title The title to set.
    222      */
    223     public void setTitle(String title) {
    224         this.title = title;
    225     }
    226
    227     static class IncludeTemplate {
    228         protected void include(PortletRequestDispatcher dispatcher, RenderRequest req, RenderResponse res) throws PortletException, IOException{
    229             try {
    230                 dispatcher.include(req, res);
    231             }
    232             catch(PortletException e) {
    233                 when(e);
    234                 throw e;
    235             }
    236             catch(IOException e) {
    237                 when(e);
    238                 throw e;
    239             }
    240         }
    241
    242         protected void when(PortletException e) {}
    243
    244         protected void when(IOException e) {}
    245     }
    246 }