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 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
132 finalLocation = finalLocation.substring(0, finalLocation
133 .lastIndexOf("."));
134 res.setRenderParameter(PortletActionConstants.ACTION_PARAM, finalLocation);
135 } else {
136
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 }