View Javadoc

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