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