001: /*
002: * $Id: PortletResult.java 568895 2007-08-23 08:57:36Z rgielen $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts2.portlet.result;
022:
023: import com.opensymphony.xwork2.ActionInvocation;
024: import com.opensymphony.xwork2.util.TextUtils;
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogFactory;
027: import org.apache.struts2.ServletActionContext;
028: import org.apache.struts2.dispatcher.StrutsResultSupport;
029: import org.apache.struts2.portlet.PortletActionConstants;
030: import org.apache.struts2.portlet.context.PortletActionContext;
031:
032: import javax.portlet.*;
033: import javax.servlet.ServletContext;
034: import javax.servlet.ServletException;
035: import javax.servlet.http.HttpServletRequest;
036: import javax.servlet.http.HttpServletResponse;
037: import java.io.IOException;
038: import java.util.StringTokenizer;
039: import java.util.Map;
040:
041: /**
042: * Result type that includes a JSP to render.
043: *
044: */
045: public class PortletResult extends StrutsResultSupport implements
046: PortletActionConstants {
047:
048: private static final long serialVersionUID = 434251393926178567L;
049:
050: /**
051: * Logger instance.
052: */
053: private static final Log LOG = LogFactory
054: .getLog(PortletResult.class);
055:
056: private String contentType = "text/html";
057:
058: private String title;
059:
060: public PortletResult() {
061: super ();
062: }
063:
064: public PortletResult(String location) {
065: super (location);
066: }
067:
068: /**
069: * Execute the result. Obtains the
070: * {@link javax.portlet.PortletRequestDispatcher}from the
071: * {@link PortletActionContext}and includes the JSP.
072: *
073: * @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)
074: */
075: public void doExecute(String finalLocation,
076: ActionInvocation actionInvocation) throws Exception {
077:
078: if (PortletActionContext.isRender()) {
079: executeRenderResult(finalLocation);
080: } else if (PortletActionContext.isEvent()) {
081: executeActionResult(finalLocation, actionInvocation);
082: } else {
083: executeRegularServletResult(finalLocation, actionInvocation);
084: }
085: }
086:
087: /**
088: * Executes the regular servlet result.
089: *
090: * @param finalLocation
091: * @param actionInvocation
092: */
093: private void executeRegularServletResult(String finalLocation,
094: ActionInvocation actionInvocation) throws ServletException,
095: IOException {
096: ServletContext ctx = ServletActionContext.getServletContext();
097: HttpServletRequest req = ServletActionContext.getRequest();
098: HttpServletResponse res = ServletActionContext.getResponse();
099: try {
100: ctx.getRequestDispatcher(finalLocation).include(req, res);
101: } catch (ServletException e) {
102: LOG.error("ServletException including " + finalLocation, e);
103: throw e;
104: } catch (IOException e) {
105: LOG.error("IOException while including result '"
106: + finalLocation + "'", e);
107: throw e;
108: }
109: }
110:
111: /**
112: * Executes the action result.
113: *
114: * @param finalLocation
115: * @param invocation
116: */
117: protected void executeActionResult(String finalLocation,
118: ActionInvocation invocation) {
119: LOG.debug("Executing result in Event phase");
120: ActionResponse res = PortletActionContext.getActionResponse();
121: Map sessionMap = invocation.getInvocationContext().getSession();
122: LOG.debug("Setting event render parameter: " + finalLocation);
123: if (finalLocation.indexOf('?') != -1) {
124: convertQueryParamsToRenderParams(res, finalLocation
125: .substring(finalLocation.indexOf('?') + 1));
126: finalLocation = finalLocation.substring(0, finalLocation
127: .indexOf('?'));
128: }
129: if (finalLocation.endsWith(".action")) {
130: // View is rendered with a view action...luckily...
131: finalLocation = finalLocation.substring(0, finalLocation
132: .lastIndexOf("."));
133: res.setRenderParameter(ACTION_PARAM, finalLocation);
134: } else {
135: // View is rendered outside an action...uh oh...
136: res.setRenderParameter(PortletActionConstants.ACTION_PARAM,
137: "renderDirect");
138: sessionMap.put(RENDER_DIRECT_LOCATION, finalLocation);
139: }
140: res.setRenderParameter(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)
169: throws PortletException, IOException {
170: LOG.debug("Executing result in Render phase");
171: PortletConfig cfg = PortletActionContext.getPortletConfig();
172: RenderRequest req = PortletActionContext.getRenderRequest();
173: RenderResponse res = PortletActionContext.getRenderResponse();
174: LOG.debug("PortletConfig: " + cfg);
175: LOG.debug("RenderRequest: " + req);
176: LOG.debug("RenderResponse: " + res);
177: res.setContentType(contentType);
178: if (TextUtils.stringSet(title)) {
179: res.setTitle(title);
180: }
181: LOG.debug("Location: " + finalLocation);
182: PortletRequestDispatcher dispatcher = cfg.getPortletContext()
183: .getRequestDispatcher(finalLocation);
184: if (dispatcher == null) {
185: throw new PortletException(
186: "Could not locate dispatcher for '" + finalLocation
187: + "'");
188: }
189: new IncludeTemplate() {
190: protected void when(PortletException e) {
191: LOG.error("PortletException while dispatching to '"
192: + finalLocation + "'");
193: }
194:
195: protected void when(IOException e) {
196: LOG.error("IOException while dispatching to '"
197: + finalLocation + "'");
198: }
199: }.include(dispatcher, req, res);
200: }
201:
202: /**
203: * Sets the content type.
204: *
205: * @param contentType The content type to set.
206: */
207: public void setContentType(String contentType) {
208: this .contentType = contentType;
209: }
210:
211: /**
212: * Sets the title.
213: *
214: * @param title The title to set.
215: */
216: public void setTitle(String title) {
217: this .title = title;
218: }
219:
220: static class IncludeTemplate {
221: protected void include(PortletRequestDispatcher dispatcher,
222: RenderRequest req, RenderResponse res)
223: throws PortletException, IOException {
224: try {
225: dispatcher.include(req, res);
226: } catch (PortletException e) {
227: when(e);
228: throw e;
229: } catch (IOException e) {
230: when(e);
231: throw e;
232: }
233: }
234:
235: protected void when(PortletException e) {
236: }
237:
238: protected void when(IOException e) {
239: }
240: }
241: }
|