1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.container;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.OutputStreamWriter;
22 import java.io.PrintWriter;
23 import java.io.StringWriter;
24 import java.util.Timer;
25 import java.util.TimerTask;
26
27 import javax.portlet.ActionRequest;
28 import javax.portlet.ActionResponse;
29 import javax.portlet.Portlet;
30 import javax.portlet.RenderRequest;
31 import javax.portlet.RenderResponse;
32 import javax.portlet.UnavailableException;
33 import javax.servlet.RequestDispatcher;
34 import javax.servlet.ServletConfig;
35 import javax.servlet.ServletContext;
36 import javax.servlet.ServletException;
37 import javax.servlet.http.HttpServlet;
38 import javax.servlet.http.HttpServletRequest;
39 import javax.servlet.http.HttpServletRequestWrapper;
40 import javax.servlet.http.HttpServletResponse;
41
42 import org.apache.jetspeed.container.session.PortalSessionsManager;
43 import org.apache.jetspeed.request.RequestContext;
44 import org.apache.jetspeed.services.JetspeedPortletServices;
45 import org.apache.jetspeed.services.PortletServices;
46 import org.apache.jetspeed.tools.pamanager.PortletApplicationManagement;
47 import org.apache.jetspeed.util.DirectoryHelper;
48 import org.apache.jetspeed.aggregator.CurrentWorkerContext;
49
50 /***
51 * Jetspeed Container entry point.
52 *
53 * @author <a href="mailto:david@bluesunrise.com">David Sean Taylor</a>
54 * @version $Id: JetspeedContainerServlet.java 593180 2007-11-08 15:00:35Z weaver $
55 */
56 public class JetspeedContainerServlet extends HttpServlet
57 {
58 private String contextName;
59 private boolean started = false;
60 private Timer startTimer = null;
61 private PortalSessionsManager psm;
62 private String contextPath;
63
64
65
66
67 private static final String JCS = "JetspeedContainerServlet: ";
68 private static final String INIT_START_MSG = JCS + "starting initialization of Portlet Application at: ";
69 private static final String TRY_START_MSG = JCS + "attemping to start Portlet Application at: ";
70 private static final String STARTED_MSG = JCS + "started Portlet Application at: ";
71 private static final String INIT_FAILED_MSG = JCS + "initialization failed for Portlet Application at: ";
72 private static final String INIT_DONE_MSG = JCS + "initialization done for Portlet Application at: ";
73 private static final String STOP_MSG = JCS + "shutting down portlet application at: ";
74 private static final String STOP_FAILED_MSG = JCS + "shutting down error for portlet application at: ";
75
76 public synchronized final void init(ServletConfig config) throws ServletException
77 {
78 synchronized (this.getClass())
79 {
80 super.init(config);
81
82 ServletContext context = getServletContext();
83
84 started = false;
85 startTimer = null;
86 contextName = config.getInitParameter("contextName");
87 contextPath = config.getInitParameter("contextPath");
88
89 if (null == contextName || contextName.length() == 0)
90 {
91 contextName = null;
92
93 throw new ServletException(JCS + "Portlet Application contextName not supplied in Init Parameters.");
94 }
95
96 if (null == contextPath || contextPath.length() == 0)
97 {
98 contextPath = "/"+contextName;
99 }
100 else if(!contextPath.startsWith("/"))
101 {
102 throw new ServletException(JCS + "Portlet Application contextPath must start with a \"/\".");
103 }
104
105
106 String paDir = context.getRealPath("/");
107 if ( paDir == null )
108 {
109 throw new ServletException(JCS + " Initialization of PortletApplication at "+contextName+" without access to its real path not supported");
110 }
111
112 context.log(INIT_START_MSG + contextName);
113 System.out.println(INIT_START_MSG + contextName);
114
115 try
116 {
117 startPortletApplication(context, paDir, Thread.currentThread().getContextClassLoader());
118 }
119 catch (Exception e)
120 {
121 String message = INIT_FAILED_MSG + contextName;
122 context.log(message, e);
123 System.err.println(message);
124 throw new ServletException(message, e);
125 }
126
127 context.log(INIT_DONE_MSG + contextName);
128 System.out.println(INIT_DONE_MSG + contextName);
129 }
130 }
131
132 private void startPortletApplication(final ServletContext context, final String paDir, final ClassLoader paClassLoader)
133 throws ServletException
134 {
135
136
137
138
139
140
141
142
143
144
145
146
147 final String START_DELAYED_MSG = JCS + "Could not yet start portlet application at: "+contextName+". Starting back ground thread to start when the portal comes online.";
148 context.log(START_DELAYED_MSG);
149 startTimer = new Timer(true);
150 startTimer.schedule(
151 new TimerTask() {
152 public void run() {
153 synchronized(contextName)
154 {
155 if (startTimer != null)
156 {
157 if (attemptStart(context, contextName, contextPath, paDir, paClassLoader)) {
158 startTimer.cancel();
159 startTimer = null;
160 } else {
161 context.log(START_DELAYED_MSG);
162 }
163 }
164 }
165 }
166 },
167
168 1,
169 10000);
170 }
171
172 private boolean attemptStart(ServletContext context, String contextName, String contextPath, String paDir, ClassLoader paClassLoader)
173 {
174 try
175 {
176 context.log(TRY_START_MSG + contextPath);
177 PortletServices services = JetspeedPortletServices.getSingleton();
178 if (services != null)
179 {
180 PortletApplicationManagement pam =
181 (PortletApplicationManagement)services.getService("PAM");
182
183 if (pam != null && pam.isStarted())
184 {
185 DirectoryHelper paDirHelper = new DirectoryHelper(new File(paDir));
186 pam.startPortletApplication(contextName, contextPath, paDirHelper, paClassLoader);
187 started = true;
188 psm = (PortalSessionsManager)services.getService(PortalSessionsManager.SERVICE_NAME);
189
190 context.log(STARTED_MSG + contextPath);
191 return true;
192 }
193 }
194 }
195 catch (Exception e)
196 {
197 context.log(INIT_FAILED_MSG + contextPath, e);
198 return true;
199 }
200 return false;
201 }
202
203
204
205
206
207 /***
208 * The primary method invoked when the Jetspeed servlet is executed.
209 *
210 * @param request Servlet request.
211 * @param ressponse Servlet response.
212 * @exception IOException a servlet exception.
213 * @exception ServletException a servlet exception.
214 */
215 public final void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
216 {
217 String portletName = null;
218 Integer method = ContainerConstants.METHOD_NOOP;
219 Portlet portlet = null;
220 boolean destroyPortlet = false;
221 boolean isParallelMode = false;
222
223 try
224 {
225 isParallelMode = CurrentWorkerContext.getParallelRenderingMode();
226
227 if (isParallelMode)
228 {
229 method = (Integer) CurrentWorkerContext.getAttribute(ContainerConstants.METHOD_ID);
230 }
231 else
232 {
233 method = (Integer) request.getAttribute(ContainerConstants.METHOD_ID);
234 }
235 if (method == ContainerConstants.METHOD_NOOP)
236 {
237 return;
238 }
239 if (isParallelMode)
240 {
241 portlet = (Portlet) CurrentWorkerContext.getAttribute(ContainerConstants.PORTLET);
242 portletName = (String) CurrentWorkerContext.getAttribute(ContainerConstants.PORTLET_NAME);
243 }
244 else
245 {
246 portlet = (Portlet)request.getAttribute(ContainerConstants.PORTLET);
247 portletName = (String)request.getAttribute(ContainerConstants.PORTLET_NAME);
248 request.removeAttribute(ContainerConstants.PORTLET);
249 }
250
251 if (method == ContainerConstants.METHOD_ACTION)
252 {
253 ActionRequest actionRequest = (ActionRequest) request.getAttribute(ContainerConstants.PORTLET_REQUEST);
254 ActionResponse actionResponse = (ActionResponse) request.getAttribute(ContainerConstants.PORTLET_RESPONSE);
255
256 ((HttpServletRequestWrapper)((HttpServletRequestWrapper)actionRequest).getRequest()).setRequest(request);
257
258 portlet.processAction(actionRequest, actionResponse);
259 }
260 else if (method == ContainerConstants.METHOD_RENDER)
261 {
262 RenderRequest renderRequest = null;
263 RenderResponse renderResponse = null;
264
265 if (isParallelMode)
266 {
267 renderRequest = (RenderRequest) CurrentWorkerContext.getAttribute(ContainerConstants.PORTLET_REQUEST);
268 renderResponse = (RenderResponse) CurrentWorkerContext.getAttribute(ContainerConstants.PORTLET_RESPONSE);
269 }
270 else
271 {
272 renderRequest = (RenderRequest) request.getAttribute(ContainerConstants.PORTLET_REQUEST);
273 renderResponse = (RenderResponse) request.getAttribute(ContainerConstants.PORTLET_RESPONSE);
274 }
275
276 ((HttpServletRequestWrapper)((HttpServletRequestWrapper)renderRequest).getRequest()).setRequest(request);
277 portlet.render(renderRequest, renderResponse);
278 }
279
280
281 return;
282 }
283 catch (Throwable t)
284 {
285 if ( t instanceof UnavailableException )
286 {
287
288 destroyPortlet = true;
289 }
290
291 if (method != ContainerConstants.METHOD_ACTION)
292 {
293 ServletContext context = getServletContext();
294 context.log(JCS + "Error rendering portlet \"" + portletName + "\": " + t.toString(), t);
295 try
296 {
297 String errorTemplate = getInitParameter("portal.error.page");
298 if (errorTemplate == null)
299 {
300 errorTemplate = "/WEB-INF/templates/generic/html/error.vm";
301 }
302 if (null != context.getResource(errorTemplate))
303 {
304 RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(errorTemplate);
305 request.setAttribute("e", t);
306 StringWriter stackTrace = new StringWriter();
307 t.printStackTrace(new PrintWriter(stackTrace));
308 request.setAttribute("stacktrace", stackTrace.toString());
309 dispatcher.include(request, response);
310 }
311 else
312 {
313 displayPortletNotAvailableMessage(t, response, portletName);
314 }
315 }
316 catch (Throwable e)
317 {
318 displayPortletNotAvailableMessage(t, response, portletName);
319 }
320 finally
321 {
322 t.printStackTrace();
323 }
324 }
325 else
326 {
327 if ( t instanceof RuntimeException )
328 {
329 throw (RuntimeException)t;
330 }
331 else if (t instanceof IOException )
332 {
333 throw (IOException)t;
334 }
335 else if (t instanceof ServletException)
336 {
337 throw (ServletException)t;
338 }
339 else
340 {
341 throw new ServletException(t);
342 }
343 }
344 }
345 finally
346 {
347 if ( destroyPortlet )
348 {
349
350 try
351 {
352 portlet.destroy();
353 }
354 catch (Exception e)
355 {
356
357 }
358 }
359 if (psm != null)
360 {
361 RequestContext rc = (RequestContext)request.getAttribute(RequestContext.REQUEST_PORTALENV);
362 psm.checkMonitorSession(contextName,rc.getRequest().getSession(),request.getSession(false));
363 }
364 }
365 }
366
367 private void displayPortletNotAvailableMessage(Throwable t, HttpServletResponse response, String portletName)
368 throws IOException
369 {
370 getServletContext().log(JCS + "Error rendering JetspeedContainerServlet error page: " + t.toString(), t);
371 PrintWriter directError;
372 try
373 {
374 directError = new PrintWriter(response.getWriter());
375 }
376 catch (IllegalStateException e)
377 {
378
379 directError = new PrintWriter(new OutputStreamWriter(response.getOutputStream()));
380 }
381 directError.write("Portlet is Not Available: " + portletName + "<br/>Reason: " + t.getMessage());
382
383 directError.close();
384 }
385
386 /***
387 * In this application doGet and doPost are the same thing.
388 *
389 * @param req Servlet request.
390 * @param res Servlet response.
391 * @exception IOException a servlet exception.
392 * @exception ServletException a servlet exception.
393 */
394 public final void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
395 {
396 doGet(req, res);
397 }
398
399
400
401
402
403 public final void destroy()
404 {
405 if ( contextName != null )
406 {
407 synchronized (contextName)
408 {
409 if ( startTimer != null )
410 {
411 startTimer.cancel();
412 startTimer = null;
413 }
414 else if ( started )
415 {
416 started = false;
417 PortletServices services = JetspeedPortletServices.getSingleton();
418 if (services != null)
419 {
420 PortletApplicationManagement pam =
421 (PortletApplicationManagement)services.getService("PAM");
422
423 if (pam != null)
424 {
425 getServletContext().log(STOP_MSG + contextName);
426 try
427 {
428 pam.stopPortletApplication(contextName);
429 }
430 catch (Exception e)
431 {
432 getServletContext().log(STOP_FAILED_MSG + contextName, e);
433 }
434 }
435 }
436 contextName = null;
437 psm = null;
438 }
439 }
440 }
441 }
442 }