1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.portals.bridges.struts;
18
19 import java.io.IOException;
20 import java.io.PrintWriter;
21
22 import javax.portlet.ActionRequest;
23 import javax.portlet.ActionResponse;
24 import javax.portlet.GenericPortlet;
25 import javax.portlet.PortletConfig;
26 import javax.portlet.PortletException;
27 import javax.portlet.PortletRequest;
28 import javax.portlet.PortletResponse;
29 import javax.portlet.PortletSession;
30 import javax.portlet.RenderRequest;
31 import javax.portlet.RenderResponse;
32 import javax.servlet.RequestDispatcher;
33 import javax.servlet.ServletContext;
34 import javax.servlet.ServletException;
35 import javax.servlet.http.HttpServletRequest;
36 import javax.servlet.http.HttpServletResponse;
37 import javax.servlet.http.HttpSession;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.apache.portals.bridges.common.ServletContextProvider;
42 import org.apache.portals.bridges.struts.config.StrutsPortletConfig;
43 import org.apache.portals.bridges.struts.util.EmptyHttpServletResponseWrapper;
44 import org.apache.portals.bridges.util.ServletPortletSessionProxy;
45
46 /***
47 * StrutsPortlet
48 *
49 * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
50 * @version $Id: StrutsPortlet.java 549654 2007-06-22 00:52:52Z ate $
51 */
52 public class StrutsPortlet extends GenericPortlet
53 {
54 /***
55 * Name of class implementing {@link ServletContextProvider}
56 */
57 public static final String PARAM_SERVLET_CONTEXT_PROVIDER = "ServletContextProvider";
58 /***
59 * Name of portlet preference for Struts Portlet Config Location
60 */
61 public static final String STRUTS_PORTLET_CONFIG_LOCATION = "StrutsPortletConfigLocation";
62
63 public static final String PORTLET_SCOPE_STRUTS_SESSION = "PortletScopeStrutsSession";
64 /***
65 * Name of portlet preference for Action page
66 */
67 public static final String PARAM_ACTION_PAGE = "ActionPage";
68 /***
69 * Name of portlet preference for Custom page
70 */
71 public static final String PARAM_CUSTOM_PAGE = "CustomPage";
72 /***
73 * Name of portlet preference for Edit page
74 */
75 public static final String PARAM_EDIT_PAGE = "EditPage";
76 /***
77 * Name of portlet preference for Edit page
78 */
79 public static final String PARAM_HELP_PAGE = "HelpPage";
80 /***
81 * Name of portlet preference for View page
82 */
83 public static final String PARAM_VIEW_PAGE = "ViewPage";
84 /***
85 * Default URL for the action page.
86 */
87 private String defaultActionPage = null;
88 /***
89 * Default URL for the custom page.
90 */
91 private String defaultCustomPage = null;
92 /***
93 * Default URL for the edit page.
94 */
95 private String defaultEditPage = null;
96 /***
97 * Default URL for the help page.
98 */
99 private String defaultHelpPage = null;
100 /***
101 * Default URL for the view page.
102 */
103 private String defaultViewPage = null;
104 private ServletContextProvider servletContextProvider;
105 private boolean portletScopeStrutsSession = false;
106 private static final Log log = LogFactory.getLog(StrutsPortlet.class);
107 public static final String REQUEST_TYPE = "org.apache.portals.bridges.struts.request_type";
108 public static final String PAGE_URL = "org.apache.portals.bridges.struts.page_url";
109 public static final String ORIGIN_URL = "org.apache.portals.bridges.struts.origin_url";
110 public static final String REDIRECT_PAGE_URL = "org.apache.portals.bridges.struts.redirect_page_url";
111 public static final String REDIRECT_URL = "org.apache.portals.bridges.struts.redirect_url";
112 public static final String RENDER_CONTEXT = "org.apache.portals.bridges.struts.render_context";
113 public static final String ERROR_CONTEXT = "org.apache.portals.bridges.struts.error_context";
114 public static final String PORTLET_NAME = "org.apache.portals.bridges.struts.portlet_name";
115 public static final String STRUTS_PORTLET_CONFIG = "org.apache.portals.bridges.struts.portlet_config";
116 public static final String DEFAULT_STRUTS_PORTLET_CONFIG_LOCATION = "/WEB-INF/struts-portlet-config.xml";
117 public static final String SERVLET_PORTLET_SESSION_PROXY = "org.apache.portals.bridges.util.servlet_portlet_session_proxy";
118 public static final String SERVLET_PORTLET_APPLICATION_SESSION = "org.apache.portals.bridges.util.servlet_portlet_application_session";
119 public static final String ACTION_REQUEST = "ACTION";
120 public static final String VIEW_REQUEST = "VIEW";
121 public static final String CUSTOM_REQUEST = "CUSTOM";
122 public static final String EDIT_REQUEST = "EDIT";
123 public static final String HELP_REQUEST = "HELP";
124
125 private StrutsPortletConfig strutsPortletConfig;
126
127 public void init(PortletConfig config) throws PortletException
128 {
129 super.init(config);
130 String contextProviderClassName = getContextProviderClassNameParameter(config);
131 if (contextProviderClassName == null)
132 throw new PortletException("Portlet " + config.getPortletName()
133 + " is incorrectly configured. Init parameter "
134 + PARAM_SERVLET_CONTEXT_PROVIDER + " not specified");
135 if (contextProviderClassName != null)
136 {
137 try
138 {
139 Class clazz = Class.forName(contextProviderClassName);
140 if (clazz != null)
141 {
142 Object obj = clazz.newInstance();
143 if (ServletContextProvider.class.isInstance(obj))
144 {
145 servletContextProvider = (ServletContextProvider) obj;
146 }
147 else
148 throw new PortletException("class not found");
149 }
150 } catch (Exception e)
151 {
152 if (e instanceof PortletException)
153 throw (PortletException) e;
154 e.printStackTrace();
155 throw new PortletException("Cannot load", e);
156 }
157 }
158 if (servletContextProvider == null)
159 throw new PortletException("Portlet " + config.getPortletName()
160 + " is incorrectly configured. Invalid init parameter "
161 + PARAM_SERVLET_CONTEXT_PROVIDER + " value "
162 + contextProviderClassName);
163 this.portletScopeStrutsSession = getPortletScopeStrutsSessionParameter(config).booleanValue();
164 this.defaultActionPage = getActionPageParameter(config);
165 this.defaultCustomPage = getCustomPageParameter(config);
166 this.defaultEditPage = getEditPageParameter(config);
167 this.defaultViewPage = getViewPageParameter(config);
168 this.defaultHelpPage = getHelpPageParameter(config);
169
170 if (this.defaultViewPage == null)
171 {
172
173
174
175 throw new PortletException(
176 "Portlet "
177 + config.getPortletName()
178 + " is incorrectly configured. No default View page is defined.");
179 }
180 if (defaultActionPage == null)
181 defaultActionPage = defaultViewPage;
182 if (defaultCustomPage == null)
183 defaultCustomPage = defaultViewPage;
184 if (defaultHelpPage == null)
185 defaultHelpPage = defaultViewPage;
186 if (defaultEditPage == null)
187 defaultEditPage = defaultViewPage;
188
189 strutsPortletConfig = new StrutsPortletConfig();
190 String strutsPortletConfigLocation = getStrutsPortletConfigLocationParameter(config);
191 if ( strutsPortletConfigLocation == null )
192 {
193 strutsPortletConfigLocation = DEFAULT_STRUTS_PORTLET_CONFIG_LOCATION;
194 }
195 strutsPortletConfig.loadConfig(config.getPortletContext(),strutsPortletConfigLocation);
196 config.getPortletContext().setAttribute(STRUTS_PORTLET_CONFIG,strutsPortletConfig);
197 }
198
199 protected String getContextProviderClassNameParameter(PortletConfig config)
200 {
201 return config.getInitParameter(PARAM_SERVLET_CONTEXT_PROVIDER);
202 }
203
204 protected ServletContextProvider getServletContextProvider()
205 {
206 return servletContextProvider;
207 }
208
209 protected ServletContext getServletContext(GenericPortlet portlet, PortletRequest request, PortletResponse response)
210 {
211 return getServletContextProvider().getServletContext(portlet);
212 }
213
214 protected HttpServletRequest getHttpServletRequest(GenericPortlet portlet, PortletRequest request, PortletResponse response)
215 {
216 return getServletContextProvider().getHttpServletRequest(portlet, request);
217 }
218
219 protected HttpServletResponse getHttpServletResponse(GenericPortlet portlet, PortletRequest request, PortletResponse response)
220 {
221 return getServletContextProvider().getHttpServletResponse(portlet, response);
222 }
223
224 protected String getStrutsPageURL(PortletRequest request)
225 {
226 if ( ACTION_REQUEST.equals(request.getAttribute(REQUEST_TYPE)))
227 {
228 return request.getParameter(StrutsPortletURL.PAGE);
229 }
230 return request.getParameter(StrutsPortletURL.PAGE+request.getPortletMode().toString());
231 }
232
233 protected String getStrutsOriginURL(PortletRequest request)
234 {
235 if ( ACTION_REQUEST.equals(request.getAttribute(REQUEST_TYPE)))
236 {
237 return request.getParameter(StrutsPortletURL.ORIGIN);
238 }
239 return request.getParameter(StrutsPortletURL.ORIGIN+request.getPortletMode().toString());
240 }
241
242 protected String getKeepRenderAttributes(PortletRequest request)
243 {
244 return request.getParameter(StrutsPortletURL.KEEP_RENDER_ATTRIBUTES+request.getPortletMode().toString());
245 }
246
247 protected String getActionPageParameter(PortletConfig config)
248 {
249 return config.getInitParameter(PARAM_ACTION_PAGE);
250 }
251
252 protected String getCustomPageParameter(PortletConfig config)
253 {
254 return config.getInitParameter(PARAM_CUSTOM_PAGE);
255 }
256
257 protected String getEditPageParameter(PortletConfig config)
258 {
259 return config.getInitParameter(PARAM_EDIT_PAGE);
260 }
261
262 protected String getViewPageParameter(PortletConfig config)
263 {
264 return config.getInitParameter(PARAM_VIEW_PAGE);
265 }
266
267 protected String getHelpPageParameter(PortletConfig config)
268 {
269 return config.getInitParameter(PARAM_HELP_PAGE);
270 }
271
272 protected String getStrutsPortletConfigLocationParameter(PortletConfig config)
273 {
274 return config.getInitParameter(STRUTS_PORTLET_CONFIG_LOCATION);
275 }
276
277 protected Boolean getPortletScopeStrutsSessionParameter(PortletConfig config)
278 {
279 return Boolean.valueOf(config.getInitParameter(PORTLET_SCOPE_STRUTS_SESSION));
280 }
281
282 public void doEdit(RenderRequest request, RenderResponse response)
283 throws PortletException, IOException
284 {
285 processRequest(request, response, defaultEditPage, StrutsPortlet.EDIT_REQUEST);
286 }
287 public void doHelp(RenderRequest request, RenderResponse response)
288 throws PortletException, IOException
289 {
290 processRequest(request, response, defaultHelpPage, StrutsPortlet.HELP_REQUEST);
291 }
292 public void doCustom(RenderRequest request, RenderResponse response)
293 throws PortletException, IOException
294 {
295 processRequest(request, response, defaultCustomPage,
296 StrutsPortlet.CUSTOM_REQUEST);
297 }
298 public void doView(RenderRequest request, RenderResponse response)
299 throws PortletException, IOException
300 {
301 processRequest(request, response, defaultViewPage, StrutsPortlet.VIEW_REQUEST);
302 }
303 public void processAction(ActionRequest request, ActionResponse response)
304 throws PortletException, IOException
305 {
306 processRequest(request, response, defaultActionPage,
307 StrutsPortlet.ACTION_REQUEST);
308 }
309 protected void processRequest(PortletRequest request, PortletResponse response,
310 String defaultPage, String requestType) throws PortletException,
311 IOException
312 {
313 ServletContext servletContext = getServletContext(this, request, response);
314 HttpServletRequest req = getHttpServletRequest(this, request, response);
315 HttpServletResponse res = getHttpServletResponse(this, request, response);
316 String portletName = this.getPortletConfig().getPortletName();
317 req.setAttribute(PORTLET_NAME, portletName);
318 boolean actionRequest = ACTION_REQUEST.equals(requestType);
319
320
321 req.setAttribute(StrutsPortlet.REQUEST_TYPE, requestType);
322
323 PortletSession portletSession = request.getPortletSession();
324
325 try
326 {
327 StrutsPortletErrorContext errorContext = (StrutsPortletErrorContext) portletSession.getAttribute(StrutsPortlet.ERROR_CONTEXT);
328 if (errorContext != null)
329 {
330 if (!actionRequest)
331 {
332 portletSession.removeAttribute(StrutsPortlet.ERROR_CONTEXT);
333 renderError(res, errorContext);
334 }
335 return;
336 }
337
338 String keepRenderAttributes = null;
339
340 if ( !actionRequest )
341 {
342 keepRenderAttributes = getKeepRenderAttributes(request);
343 }
344 if ( keepRenderAttributes == null )
345 {
346 strutsPortletConfig.getRenderContextAttributes().clearAttributes(portletSession);
347 }
348 else
349 {
350 strutsPortletConfig.getRenderContextAttributes().restoreAttributes(request);
351 }
352
353 String path = null;
354 String pageURL = getStrutsPageURL(request);
355
356 if (pageURL == null)
357 {
358 path = defaultPage;
359 }
360 else
361 {
362 path = pageURL;
363 }
364 if ( !actionRequest )
365 {
366
367 StrutsPortletRenderContext renderContext = (StrutsPortletRenderContext)portletSession.getAttribute(RENDER_CONTEXT);
368 if ( renderContext != null )
369 {
370 portletSession.removeAttribute(RENDER_CONTEXT);
371 req.setAttribute(RENDER_CONTEXT, renderContext);
372 }
373 }
374
375 if (log.isDebugEnabled())
376 log.debug("process path: " + path + ", requestType: " + requestType);
377
378 RequestDispatcher rd = servletContext.getRequestDispatcher(path);
379 if (rd != null)
380 {
381 if (actionRequest)
382 {
383 res = new EmptyHttpServletResponseWrapper(res);
384
385
386
387
388
389
390 if ( req.getAttribute("javax.portlet.config") == null )
391 {
392 req.setAttribute("javax.portlet.config", getPortletConfig());
393 }
394 if ( req.getAttribute("javax.portlet.request") == null )
395 {
396 req.setAttribute("javax.portlet.request", request);
397 }
398 if ( req.getAttribute("javax.portlet.response") == null )
399 {
400 req.setAttribute("javax.portlet.response", response);
401 }
402 String origin = getStrutsOriginURL(request);
403 if ( origin == null )
404 {
405 origin = defaultPage;
406 }
407 request.setAttribute(StrutsPortlet.ORIGIN_URL, origin);
408 }
409 if (path != null)
410 {
411 req.setAttribute(StrutsPortlet.PAGE_URL, path);
412 }
413
414 HttpSession proxiedSession = null;
415 if ( portletScopeStrutsSession )
416 {
417 proxiedSession = (HttpSession)portletSession.getAttribute(SERVLET_PORTLET_SESSION_PROXY);
418 if (proxiedSession == null)
419 {
420 proxiedSession = ServletPortletSessionProxy.createProxy(req);
421 portletSession.setAttribute(SERVLET_PORTLET_SESSION_PROXY, proxiedSession);
422 }
423 }
424 req.setAttribute(SERVLET_PORTLET_APPLICATION_SESSION, req.getSession());
425 try
426 {
427 rd.include(new PortletServletRequestWrapper(servletContext, req, proxiedSession), res);
428 }
429 catch (ServletException e)
430 {
431 if (log.isErrorEnabled())
432 log.error("Include exception", e);
433 errorContext = new StrutsPortletErrorContext();
434 errorContext.setError(e);
435 req.setAttribute(StrutsPortlet.ERROR_CONTEXT, errorContext);
436 if (!actionRequest)
437 renderError(res, errorContext);
438 }
439 if (actionRequest)
440 {
441 String renderURL;
442 if (req.getAttribute(StrutsPortlet.ERROR_CONTEXT) != null)
443 {
444 pageURL = StrutsPortletURL.getOriginURL(req);
445 if ( pageURL != null )
446 {
447 ((ActionResponse) response).setRenderParameter(StrutsPortletURL.PAGE+request.getPortletMode().toString(), pageURL);
448 }
449 if (log.isDebugEnabled())
450 log.debug("action render error context");
451 try
452 {
453 portletSession.setAttribute(StrutsPortlet.ERROR_CONTEXT,req.getAttribute(StrutsPortlet.ERROR_CONTEXT));
454 }
455 catch (IllegalStateException ise)
456 {
457
458
459
460 }
461 }
462 else
463 {
464 if ((renderURL = (String) req
465 .getAttribute(StrutsPortlet.REDIRECT_URL)) != null)
466 {
467 if (log.isDebugEnabled())
468 log.debug("action send redirect: " + renderURL);
469 ((ActionResponse) response).sendRedirect(renderURL);
470 }
471 else
472 {
473 try
474 {
475 strutsPortletConfig.getRenderContextAttributes().saveAttributes(request);
476 }
477 catch (IllegalStateException ise)
478 {
479
480
481
482 return;
483 }
484 StrutsPortletRenderContext renderContext = (StrutsPortletRenderContext)req.getAttribute(RENDER_CONTEXT);
485 if ( renderContext != null )
486 {
487 portletSession.setAttribute(RENDER_CONTEXT, renderContext);
488 }
489 ((ActionResponse) response).setRenderParameter(
490 StrutsPortletURL.KEEP_RENDER_ATTRIBUTES+request.getPortletMode().toString(), "1");
491
492 if ((renderURL = (String) req
493 .getAttribute(StrutsPortlet.REDIRECT_PAGE_URL)) != null)
494 {
495 if (log.isDebugEnabled())
496 log.debug("action render redirected page: "
497 + renderURL);
498 pageURL = renderURL;
499 }
500 if (pageURL != null)
501 {
502 if (renderURL == null && log.isWarnEnabled())
503 log.warn("Warning: Using the original action URL for render URL: " +pageURL+".\nA redirect should have been issued.");
504 ((ActionResponse) response).setRenderParameter(
505 StrutsPortletURL.PAGE+request.getPortletMode().toString(), pageURL);
506 }
507 }
508 }
509 }
510 }
511 } catch (IOException e)
512 {
513 if (log.isErrorEnabled())
514 log.error("unexpected", e);
515 throw e;
516 }
517 }
518 protected void renderError(HttpServletResponse response,
519 StrutsPortletErrorContext errorContext) throws IOException
520 {
521 PrintWriter writer = response.getWriter();
522 writer.println("<hr/><h2>Error</h2>");
523 writer.println("<table border='1'>");
524 if (errorContext.getErrorCode() != 0)
525 writer.println("<tr><td valign='top'><b>Error Code</b></td><td>"
526 + errorContext.getErrorCode() + "</td></tr>");
527 if (errorContext.getErrorMessage() != null)
528 writer.println("<tr><td valign='top'><b>Error Message</b></td><td>"
529 + errorContext.getErrorMessage() + "</td></tr>");
530 if (errorContext.getError() != null)
531 {
532 Throwable e = errorContext.getError();
533 if (e instanceof ServletException
534 && ((ServletException) e).getRootCause() != null)
535 e = ((ServletException) e).getRootCause();
536 writer.print("<tr><td valign='top'><b>Error</b></td><td>"
537 + e.getMessage() + "</td></tr>");
538 writer.print("<tr><td valign='top'><b>Error Type</b></td><td>"
539 + e.getClass().getName() + "</td></tr>");
540 writer.print("<tr><td valign='top'><b>Stacktrace</b></td><td>");
541 StackTraceElement[] elements = e.getStackTrace();
542 StringBuffer buf = new StringBuffer();
543 for (int i = 0; i < elements.length; i++)
544 buf.append(" " + elements[i].toString() + "<br>");
545 writer.print(buf.toString());
546 writer.println("</td></tr>");
547 }
548 writer.println("</table>");
549 }
550
551 public HttpSession getApplicationSession(HttpServletRequest request)
552 {
553 HttpSession appSession = (HttpSession)request.getAttribute(SERVLET_PORTLET_APPLICATION_SESSION);
554 if ( appSession == null )
555 {
556 appSession = request.getSession();
557 }
558 return appSession;
559 }
560 }