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