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