1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.portlet;
20
21 import java.io.IOException;
22
23 import javax.faces.FactoryFinder;
24 import javax.faces.application.Application;
25 import javax.faces.application.ApplicationFactory;
26 import javax.faces.application.ViewHandler;
27 import javax.faces.component.UIViewRoot;
28 import javax.faces.context.ExternalContext;
29 import javax.faces.context.FacesContext;
30 import javax.faces.context.FacesContextFactory;
31 import javax.faces.lifecycle.Lifecycle;
32 import javax.faces.lifecycle.LifecycleFactory;
33 import javax.faces.webapp.FacesServlet;
34 import javax.portlet.ActionRequest;
35 import javax.portlet.ActionResponse;
36 import javax.portlet.GenericPortlet;
37 import javax.portlet.PortletContext;
38 import javax.portlet.PortletException;
39 import javax.portlet.PortletRequest;
40 import javax.portlet.PortletResponse;
41 import javax.portlet.RenderRequest;
42 import javax.portlet.RenderResponse;
43 import javax.portlet.UnavailableException;
44
45 import org.apache.commons.logging.Log;
46 import org.apache.commons.logging.LogFactory;
47 import org.apache.myfaces.context.ReleaseableExternalContext;
48 import org.apache.myfaces.context.portlet.PortletExternalContextImpl;
49 import org.apache.myfaces.context.servlet.FacesContextImpl;
50 import org.apache.myfaces.shared_impl.webapp.webxml.WebXml;
51
52
53
54
55
56
57
58
59
60 public class MyFacesGenericPortlet extends GenericPortlet
61 {
62 private static final Log log = LogFactory.getLog(MyFacesGenericPortlet.class);
63
64
65 public static final String VIEW_ID =
66 MyFacesGenericPortlet.class.getName() + ".VIEW_ID";
67
68
69 protected static final String CURRENT_FACES_CONTEXT =
70 MyFacesGenericPortlet.class.getName() + ".CURRENT_FACES_CONTEXT";
71
72
73 protected static final String DEFAULT_VIEW = "default-view";
74
75
76 protected static final String DEFAULT_VIEW_SELECTOR = "default-view-selector";
77
78 protected static final String FACES_INIT_DONE =
79 MyFacesGenericPortlet.class.getName() + ".FACES_INIT_DONE";
80
81 protected PortletContext portletContext;
82
83 protected FacesContextFactory facesContextFactory;
84 protected Lifecycle lifecycle;
85
86 protected String defaultView;
87 protected DefaultViewSelector defaultViewSelector;
88
89
90
91
92 public MyFacesGenericPortlet()
93 {
94 }
95
96
97
98
99 public void destroy()
100 {
101 super.destroy();
102 FactoryFinder.releaseFactories();
103 }
104
105
106
107
108 public void init() throws PortletException, UnavailableException
109 {
110 this.portletContext = getPortletContext();
111 setDefaultView();
112 setDefaultViewSelector();
113 initMyFaces();
114
115 facesContextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
116
117
118
119 LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
120 lifecycle = lifecycleFactory.getLifecycle(getLifecycleId());
121 }
122
123 protected void setDefaultView() throws UnavailableException
124 {
125 this.defaultView = getPortletConfig().getInitParameter(DEFAULT_VIEW);
126 if (defaultView == null)
127 {
128 String msg = "Fatal: must specify a JSF view id as the default view in portlet.xml";
129 throw new UnavailableException(msg);
130 }
131 }
132
133 protected void setDefaultViewSelector() throws UnavailableException
134 {
135 String selectorClass = getPortletConfig().getInitParameter(DEFAULT_VIEW_SELECTOR);
136 if (selectorClass == null) return;
137
138 try
139 {
140 this.defaultViewSelector = (DefaultViewSelector)Class.forName(selectorClass).newInstance();
141 this.defaultViewSelector.setPortletContext(getPortletContext());
142 }
143 catch (Exception e)
144 {
145 log.error("Failed to load " + DEFAULT_VIEW_SELECTOR, e);
146 throw new UnavailableException(e.getMessage());
147 }
148 }
149
150 protected void setContentType(RenderRequest request, RenderResponse response)
151 {
152
153 if (response.getContentType() == null)
154 {
155 String portalPreferredContentType = request.getResponseContentType();
156 if (portalPreferredContentType != null)
157 {
158 response.setContentType(portalPreferredContentType);
159 }
160 else
161 {
162 response.setContentType("text/html");
163 }
164 }
165 }
166
167 protected String getLifecycleId()
168 {
169 String lifecycleId = getPortletConfig().getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);
170 return lifecycleId != null ? lifecycleId : LifecycleFactory.DEFAULT_LIFECYCLE;
171 }
172
173 protected void initMyFaces()
174 {
175 try
176 {
177 Boolean b = (Boolean)portletContext.getAttribute(FACES_INIT_DONE);
178
179 if (b == null || b.booleanValue() == false)
180 {
181 log.trace("Initializing MyFaces");
182
183
184 ExternalContext externalContext = new PortletExternalContextImpl(portletContext, null, null);
185
186
187
188
189
190
191
192 WebXml.init(externalContext);
193
194 portletContext.setAttribute(FACES_INIT_DONE, Boolean.TRUE);
195 }
196 else
197 {
198 log.info("MyFaces already initialized");
199 }
200 }
201 catch (Exception ex)
202 {
203 log.error("Error initializing MyFacesGenericPortlet", ex);
204 }
205
206 log.info("PortletContext '" + portletContext.getRealPath("/") + "' initialized.");
207 }
208
209
210
211
212 public void processAction(ActionRequest request, ActionResponse response)
213 throws PortletException, IOException
214 {
215 if (log.isTraceEnabled()) log.trace("called processAction");
216
217 if (sessionTimedOut(request)) return;
218
219 setPortletRequestFlag(request);
220
221 FacesContext facesContext = facesContext(request, response);
222
223 try
224 {
225 lifecycle.execute(facesContext);
226
227 if (!facesContext.getResponseComplete())
228 {
229 response.setRenderParameter(VIEW_ID, facesContext.getViewRoot().getViewId());
230 }
231
232 request.getPortletSession().setAttribute(CURRENT_FACES_CONTEXT, facesContext);
233 }
234 catch (Throwable e)
235 {
236 facesContext.release();
237 handleExceptionFromLifecycle(e);
238 }
239 }
240
241 protected void handleExceptionFromLifecycle(Throwable e)
242 throws PortletException, IOException
243 {
244 logException(e, null);
245
246 if (e instanceof IOException)
247 {
248 throw (IOException)e;
249 }
250
251 if (e instanceof PortletException)
252 {
253 throw (PortletException)e;
254 }
255
256 if (e.getMessage() != null)
257 {
258 throw new PortletException(e.getMessage(), e);
259 }
260
261 throw new PortletException(e);
262 }
263
264
265
266
267 protected void doView(RenderRequest request, RenderResponse response)
268 throws PortletException, IOException
269 {
270 facesRender(request, response);
271 }
272
273
274
275
276
277 protected void doEdit(RenderRequest request, RenderResponse response)
278 throws PortletException, IOException
279 {
280 facesRender(request, response);
281 }
282
283
284
285
286
287 protected void doHelp(RenderRequest request, RenderResponse response)
288 throws PortletException, IOException
289 {
290 facesRender(request, response);
291 }
292
293
294
295
296
297
298
299
300 protected void nonFacesRequest(RenderRequest request, RenderResponse response) throws PortletException
301 {
302 nonFacesRequest(request, response, selectDefaultView(request, response));
303 }
304
305
306
307
308
309
310
311
312
313
314 protected void nonFacesRequest(RenderRequest request, RenderResponse response, String view)
315 throws PortletException
316 {
317 if (log.isTraceEnabled()) log.trace("Non-faces request: contextPath = " + request.getContextPath());
318 setContentType(request, response);
319 ApplicationFactory appFactory =
320 (ApplicationFactory)FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
321 Application application = appFactory.getApplication();
322 ViewHandler viewHandler = application.getViewHandler();
323 FacesContext facesContext = facesContext(request, response);
324 UIViewRoot viewRoot = viewHandler.createView(facesContext, view);
325 viewRoot.setViewId(view);
326 facesContext.setViewRoot(viewRoot);
327 lifecycle.render(facesContext);
328 }
329
330 protected String selectDefaultView(RenderRequest request, RenderResponse response) throws PortletException
331 {
332 String view = this.defaultView;
333 if (this.defaultViewSelector != null)
334 {
335 String selectedView = this.defaultViewSelector.selectViewId(request, response);
336 if (selectedView != null)
337 {
338 view = selectedView;
339 }
340 }
341
342 return view;
343 }
344
345 protected FacesContext facesContext(PortletRequest request,
346 PortletResponse response)
347 {
348 return facesContextFactory.getFacesContext(portletContext,
349 request,
350 response,
351 lifecycle);
352 }
353
354 protected ReleaseableExternalContext makeExternalContext(PortletRequest request,
355 PortletResponse response)
356 {
357 return new PortletExternalContextImpl(portletContext, request, response);
358 }
359
360 protected boolean sessionTimedOut(PortletRequest request)
361 {
362 return request.getPortletSession(false) == null;
363 }
364
365 protected void setPortletRequestFlag(PortletRequest request)
366 {
367 request.getPortletSession().setAttribute(PortletUtil.PORTLET_REQUEST_FLAG, "true");
368 }
369
370
371
372
373 protected void facesRender(RenderRequest request, RenderResponse response)
374 throws PortletException, java.io.IOException
375 {
376 if (log.isTraceEnabled()) log.trace("called facesRender");
377
378 setContentType(request, response);
379
380 String viewId = request.getParameter(VIEW_ID);
381 if ((viewId == null) || sessionTimedOut(request))
382 {
383 setPortletRequestFlag(request);
384 nonFacesRequest(request, response);
385 return;
386 }
387
388 setPortletRequestFlag(request);
389
390 try
391 {
392 FacesContextImpl facesContext = (FacesContextImpl)request.
393 getPortletSession().
394 getAttribute(CURRENT_FACES_CONTEXT);
395
396
397 if (facesContext.getResponseComplete()) return;
398
399 facesContext.setExternalContext(makeExternalContext(request, response));
400 lifecycle.render(facesContext);
401 }
402 catch (Throwable e)
403 {
404 handleExceptionFromLifecycle(e);
405 }
406 }
407
408 protected void logException(Throwable e, String msgPrefix) {
409 String msg;
410 if (msgPrefix == null)
411 {
412 if (e.getMessage() == null)
413 {
414 msg = "Exception in FacesServlet";
415 }
416 else
417 {
418 msg = e.getMessage();
419 }
420 }
421 else
422 {
423 if (e.getMessage() == null)
424 {
425 msg = msgPrefix;
426 }
427 else
428 {
429 msg = msgPrefix + ": " + e.getMessage();
430 }
431 }
432
433 portletContext.log(msg, e);
434
435 Throwable cause = e.getCause();
436 if (cause != null && cause != e)
437 {
438 logException(cause, "Root cause");
439 }
440
441 if(e instanceof PortletException)
442 {
443 cause = ((PortletException) e).getCause();
444
445 if(cause != null && cause != e)
446 {
447 logException(cause, "Root cause of PortletException");
448 }
449 }
450 }
451
452 }