KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > myfaces > portlet > MyFacesGenericPortlet


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.myfaces.portlet;
17
18 import java.io.IOException JavaDoc;
19
20 import javax.faces.FactoryFinder;
21 import javax.faces.application.Application;
22 import javax.faces.application.ApplicationFactory;
23 import javax.faces.application.ViewHandler;
24 import javax.faces.component.UIViewRoot;
25 import javax.faces.context.ExternalContext;
26 import javax.faces.context.FacesContext;
27 import javax.faces.context.FacesContextFactory;
28 import javax.faces.lifecycle.Lifecycle;
29 import javax.faces.lifecycle.LifecycleFactory;
30 import javax.faces.webapp.FacesServlet;
31 import javax.portlet.ActionRequest;
32 import javax.portlet.ActionResponse;
33 import javax.portlet.GenericPortlet;
34 import javax.portlet.PortletContext;
35 import javax.portlet.PortletException;
36 import javax.portlet.PortletRequest;
37 import javax.portlet.PortletResponse;
38 import javax.portlet.RenderRequest;
39 import javax.portlet.RenderResponse;
40 import javax.portlet.UnavailableException;
41
42 import org.apache.commons.logging.Log;
43 import org.apache.commons.logging.LogFactory;
44 import org.apache.myfaces.config.FacesConfigurator;
45 import org.apache.myfaces.context.ReleaseableExternalContext;
46 import org.apache.myfaces.context.portlet.PortletExternalContextImpl;
47 import org.apache.myfaces.context.servlet.ServletFacesContextImpl;
48 import org.apache.myfaces.webapp.webxml.WebXml;
49
50 /**
51  * This portlet initializes MyFaces and converts portlet requests into
52  * JSF requests.
53  *
54  * @author Stan Silvert (latest modification by $Author: schof $)
55  * @version $Revision: 1.3 $ $Date: 2005/04/06 18:23:36 $
56  * $Log: MyFacesGenericPortlet.java,v $
57  * Revision 1.3 2005/04/06 18:23:36 schof
58  * Fixes MYFACES-101. Used a patch from Stan while @infra sorts out his karma.
59  *
60  * Revision 1.2 2005/02/10 20:24:17 matzew
61  * closed MYFACES-101 in Jira; Thanks to Stan Silvert (JBoss Group)
62  *
63  * Revision 1.1 2005/01/26 17:03:10 matzew
64  * MYFACES-86. portlet support provided by Stan Silver (JBoss Group)
65  *
66  */

67 public class MyFacesGenericPortlet extends GenericPortlet
68 {
69     private static final Log log = LogFactory.getLog(MyFacesGenericPortlet.class);
70     
71     // PortletRequest parameter
72
public static final String JavaDoc VIEW_ID =
73         MyFacesGenericPortlet.class.getName() + ".VIEW_ID";
74     
75     // PortletSession attribute
76
private static final String JavaDoc CURRENT_FACES_CONTEXT =
77         MyFacesGenericPortlet.class.getName() + ".CURRENT_FACES_CONTEXT";
78     
79     // portlet config parameter from portlet.xml
80
private static final String JavaDoc DEFAULT_VIEW = "default-view";
81     
82     // portlet config parameter from portlet.xml
83
private static final String JavaDoc DEFAULT_VIEW_SELECTOR = "default-view-selector";
84     
85     private static final String JavaDoc FACES_INIT_DONE =
86         MyFacesGenericPortlet.class.getName() + ".FACES_INIT_DONE";
87     
88     private PortletContext portletContext;
89     
90     private FacesContextFactory facesContextFactory;
91     private Lifecycle lifecycle;
92     
93     private String JavaDoc defaultView;
94     private DefaultViewSelector defaultViewSelector;
95     
96     /**
97      * Creates a new instance of MyFacesPortlet
98      */

99     public MyFacesGenericPortlet()
100     {
101     }
102     
103     /**
104      * Portlet lifecycle.
105      */

106     public void destroy()
107     {
108         super.destroy();
109         FactoryFinder.releaseFactories();
110     }
111     
112     /**
113      * Portlet lifecycle.
114      */

115     public void init() throws PortletException, UnavailableException
116     {
117         this.portletContext = getPortletContext();
118         setDefaultView();
119         setDefaultViewSelector();
120         initMyFaces();
121         
122         facesContextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
123
124         // Javadoc says: Lifecycle instance is shared across multiple simultaneous requests, it must be
125
// implemented in a thread-safe manner. So we can acquire it here once:
126
LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
127         lifecycle = lifecycleFactory.getLifecycle(getLifecycleId());
128     }
129     
130     private void setDefaultView() throws UnavailableException
131     {
132         this.defaultView = getPortletConfig().getInitParameter(DEFAULT_VIEW);
133         if (defaultView == null)
134         {
135             String JavaDoc msg = "Fatal: must specify a JSF view id as the default view in portlet.xml";
136             throw new UnavailableException(msg);
137         }
138     }
139     
140     private void setDefaultViewSelector() throws UnavailableException
141     {
142         String JavaDoc selectorClass = getPortletConfig().getInitParameter(DEFAULT_VIEW_SELECTOR);
143         if (selectorClass == null) return;
144         
145         try
146         {
147             this.defaultViewSelector = (DefaultViewSelector)Class.forName(selectorClass).newInstance();
148             this.defaultViewSelector.setPortletContext(getPortletContext());
149         }
150         catch (Exception JavaDoc e)
151         {
152             log.error("Failed to load " + DEFAULT_VIEW_SELECTOR, e);
153             throw new UnavailableException(e.getMessage());
154         }
155     }
156     
157     private String JavaDoc getLifecycleId()
158     {
159         String JavaDoc lifecycleId = getPortletConfig().getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);
160         return lifecycleId != null ? lifecycleId : LifecycleFactory.DEFAULT_LIFECYCLE;
161     }
162     
163     private void initMyFaces()
164     {
165         try
166         {
167             Boolean JavaDoc b = (Boolean JavaDoc)portletContext.getAttribute(FACES_INIT_DONE);
168
169             if (b == null || b.booleanValue() == false)
170             {
171                 log.trace("Initializing MyFaces");
172
173                 //Load the configuration
174
ExternalContext externalContext = new PortletExternalContextImpl(portletContext, null, null);
175
176                 //And configure everything
177
new FacesConfigurator(externalContext).configure();
178
179                 // parse web.xml - not sure if this is needed for portlet
180
WebXml.init(externalContext);
181
182                 portletContext.setAttribute(FACES_INIT_DONE, Boolean.TRUE);
183             }
184             else
185             {
186                 log.info("MyFaces already initialized");
187             }
188         }
189         catch (Exception JavaDoc ex)
190         {
191             log.error("Error initializing MyFacesGenericPortlet", ex);
192         }
193         
194         log.info("PortletContext '" + portletContext.getRealPath("/") + "' initialized.");
195     }
196     
197     /**
198      * Called by the portlet container to allow the portlet to process an action request.
199      */

200     public void processAction(ActionRequest request, ActionResponse response)
201             throws PortletException, IOException JavaDoc
202     {
203         if (log.isTraceEnabled()) log.trace("called processAction");
204         
205         if (sessionTimedOut(request)) return;
206         
207         setPortletRequestFlag(request);
208         
209         FacesContext facesContext = facesContext(request, response);
210                 
211         try
212         {
213             lifecycle.execute(facesContext);
214             
215             if (!facesContext.getResponseComplete())
216             {
217                 response.setRenderParameter(VIEW_ID, facesContext.getViewRoot().getViewId());
218             }
219             
220             request.getPortletSession().setAttribute(CURRENT_FACES_CONTEXT, facesContext);
221         }
222         catch (Throwable JavaDoc e)
223         {
224             facesContext.release();
225             handleExceptionFromLifecycle(e);
226         }
227     }
228
229     private void handleExceptionFromLifecycle(Throwable JavaDoc e)
230             throws PortletException, IOException JavaDoc
231     {
232         logException(e, null);
233
234         if (e instanceof IOException JavaDoc)
235         {
236             throw (IOException JavaDoc)e;
237         }
238         
239         if (e instanceof PortletException)
240         {
241             throw (PortletException)e;
242         }
243         
244         if (e.getMessage() != null)
245         {
246             throw new PortletException(e.getMessage(), e);
247         }
248         
249         throw new PortletException(e);
250     }
251     
252     /**
253      * Helper method to serve up the view mode.
254      */

255     protected void doView(RenderRequest request, RenderResponse response)
256             throws PortletException, IOException JavaDoc
257     {
258         facesRender(request, response);
259     }
260     
261     /**
262      * Helper method to serve up the edit mode. Can be overridden to add
263      * the edit mode concept to a JSF application.
264      */

265     protected void doEdit(RenderRequest request, RenderResponse response)
266             throws PortletException, IOException JavaDoc
267     {
268         facesRender(request, response);
269     }
270     
271     /**
272      * Helper method to serve up the edit mode. Can be overridden to add
273      * the help mode concept to a JSF application.
274      */

275     protected void doHelp(RenderRequest request, RenderResponse response)
276             throws PortletException, IOException JavaDoc
277     {
278         facesRender(request, response);
279     }
280     
281     // JSF Spec section 2.1.1
282
protected void nonFacesRequest(RenderRequest request, RenderResponse response) throws PortletException
283     {
284         if (log.isTraceEnabled()) log.trace("Non-faces request: contextPath = " + request.getContextPath());
285         ApplicationFactory appFactory =
286             (ApplicationFactory)FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
287         Application application = appFactory.getApplication();
288         ViewHandler viewHandler = application.getViewHandler();
289         FacesContext facesContext = facesContext(request, response);
290         UIViewRoot view = viewHandler.createView(facesContext, selectDefaultView(request, response));
291         facesContext.setViewRoot(view);
292         lifecycle.render(facesContext);
293     }
294     
295     private String JavaDoc selectDefaultView(RenderRequest request, RenderResponse response) throws PortletException
296     {
297         String JavaDoc view = this.defaultView;
298         if (this.defaultViewSelector != null)
299         {
300             String JavaDoc selectedView = this.defaultViewSelector.selectViewId(request, response);
301             if (selectedView != null)
302             {
303                 view = selectedView;
304             }
305         }
306             
307         return view;
308     }
309     
310     private FacesContext facesContext(PortletRequest request,
311                                       PortletResponse response)
312     {
313         return facesContextFactory.getFacesContext(portletContext,
314                                                    request,
315                                                    response,
316                                                    lifecycle);
317     }
318     
319     private ReleaseableExternalContext makeExternalContext(PortletRequest request,
320                                                            PortletResponse response)
321     {
322         return (ReleaseableExternalContext)new PortletExternalContextImpl(portletContext, request, response);
323     }
324     
325     private boolean sessionTimedOut(PortletRequest request)
326     {
327         return request.getPortletSession(false) == null;
328     }
329     
330     private void setPortletRequestFlag(PortletRequest request)
331     {
332         request.getPortletSession().setAttribute(PortletUtil.PORTLET_REQUEST_FLAG, "true");
333     }
334     
335     /**
336      * Render a JSF view.
337      */

338     protected void facesRender(RenderRequest request, RenderResponse response)
339             throws PortletException, java.io.IOException JavaDoc
340     {
341         if (log.isTraceEnabled()) log.trace("called facesRender");
342
343         response.setContentType("text/html");
344         
345         String JavaDoc viewId = request.getParameter(VIEW_ID);
346         if ((viewId == null) || sessionTimedOut(request))
347         {
348             setPortletRequestFlag(request);
349             nonFacesRequest(request, response);
350             return;
351         }
352        
353         setPortletRequestFlag(request);
354         
355         try
356         {
357             ServletFacesContextImpl facesContext = (ServletFacesContextImpl)request.
358                                                    getPortletSession().
359                                                    getAttribute(CURRENT_FACES_CONTEXT);
360             
361             // TODO: not sure if this can happen. Also double check this against spec section 2.1.3
362
if (facesContext.getResponseComplete()) return;
363             
364             facesContext.setExternalContext(makeExternalContext(request, response));
365             lifecycle.render(facesContext);
366         }
367         catch (Throwable JavaDoc e)
368         {
369             handleExceptionFromLifecycle(e);
370         }
371     }
372     
373     private void logException(Throwable JavaDoc e, String JavaDoc msgPrefix) {
374         String JavaDoc msg;
375         if (msgPrefix == null)
376         {
377             if (e.getMessage() == null)
378             {
379                 msg = "Exception in FacesServlet";
380             }
381             else
382             {
383                 msg = e.getMessage();
384             }
385         }
386         else
387         {
388             if (e.getMessage() == null)
389             {
390                 msg = msgPrefix;
391             }
392             else
393             {
394                 msg = msgPrefix + ": " + e.getMessage();
395             }
396         }
397
398         portletContext.log(msg, e);
399
400         Throwable JavaDoc cause = e.getCause();
401         if (cause != null && cause != e)
402         {
403             logException(cause, "Root cause");
404         }
405
406         if(e instanceof PortletException)
407         {
408             cause = ((PortletException) e).getCause();
409
410             if(cause != null && cause != e)
411             {
412                 logException(cause, "Root cause of PortletException");
413             }
414         }
415     }
416     
417 }
Popular Tags