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 }