View Javadoc

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.portals.bridges.jsf;
17  
18  import java.util.ArrayList;
19  import java.util.Collections;
20  import java.util.Iterator;
21  import java.util.List;
22  import java.util.NoSuchElementException;
23  
24  import javax.faces.FactoryFinder;
25  import javax.faces.application.Application;
26  import javax.faces.application.ApplicationFactory;
27  import javax.faces.application.FacesMessage;
28  import javax.faces.component.UIViewRoot;
29  import javax.faces.context.ExternalContext;
30  import javax.faces.context.FacesContext;
31  import javax.faces.context.ResponseStream;
32  import javax.faces.context.ResponseWriter;
33  import javax.faces.render.RenderKit;
34  import javax.faces.render.RenderKitFactory;
35  
36  import javax.portlet.ActionRequest;
37  import javax.portlet.PortletContext;
38  import javax.portlet.PortletRequest;
39  import javax.portlet.PortletResponse;
40  import javax.portlet.PortletSession;
41  
42  import org.apache.commons.logging.Log;
43  import org.apache.commons.logging.LogFactory;
44  
45  /***
46   * <p>
47   * See MyFaces project for servlet implementation.
48   * </p>
49   * <p>
50   * TODO There should be a base class shared with the MyFaces
51   * ServletFacesContextImpl.
52   * </p>
53   * 
54   * @author <a href="dlestrat@apache.org">David Le Strat </a>
55   *  
56   */
57  public class PortletFacesContextImpl extends FacesContext
58  {
59      /*** The logger. */
60      private static final Log log = LogFactory.getLog(PortletFacesContextImpl.class);
61  
62      protected static final Object NULL_DUMMY = new Object();
63  
64      /*** The message client ids. */
65      private List messageClientIds = null;
66  
67      /*** The mesages. */
68      private List messages = null;
69  
70      /*** The application. */
71      private Application application;
72  
73      /*** The portlet external context. */
74      private PortletExternalContextImpl externalContext;
75  
76      /*** The response stream. */
77      private ResponseStream responseStream = null;
78  
79      /*** The response writer. */
80      private ResponseWriter responseWriter = null;
81  
82      /*** The severity. */
83      private FacesMessage.Severity maximumSeverity = FacesMessage.SEVERITY_INFO;
84  
85      /*** The view root. */
86      private UIViewRoot viewRoot;
87  
88      /*** The render response. */
89      private boolean renderResponse = false;
90  
91      /*** Whether the response is complete. */
92      private boolean responseComplete = false;
93  
94      /*** The render kit factory. */
95      private RenderKitFactory renderKitFactory;
96  
97      /*** The JSF_VIEW_ID used to maintain the state of the view action. */
98      public static final String JSF_VIEW_ID = "jsf_viewid";
99  
100     /***
101      * @param portletContext The {@link PortletContext}.
102      * @param portletRequest The {@link PortletRequest}.
103      * @param portletResponse The {@link PortletResponse}.
104      */
105     public PortletFacesContextImpl(PortletContext portletContext, PortletRequest portletRequest,
106             PortletResponse portletResponse)
107     {
108         this.application = ((ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY))
109                 .getApplication();
110         this.renderKitFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
111         this.externalContext = new PortletExternalContextImpl(portletContext, portletRequest, portletResponse);
112         FacesContext.setCurrentInstance(this); //protected method, therefore
113         // must be called from here
114     }
115 
116     public UIViewRoot resolveViewRoot(String defaultViewName, PortletRequest portletRequest)
117     {
118         // shoot: can't get the entity id and be portable
119         PortletRequest request = (PortletRequest) externalContext.getRequest();
120         String viewId = request.getParameter(JSF_VIEW_ID);
121 
122         if (viewId == null)
123         {
124             viewId = defaultViewName;
125             if (log.isDebugEnabled())
126             {
127                 log.debug("Request view id is null.  Using default view.");
128             }
129         }
130         if (log.isDebugEnabled())
131         {
132             log.debug("Resolving view root - Using view id: " + viewId);
133         }
134 
135         if (portletRequest instanceof ActionRequest)
136         {
137             if (log.isDebugEnabled())
138             {
139                 log.debug("Resolving action: " + viewId);
140             }
141             setViewRoot(viewRoot);
142             portletRequest.setAttribute(FacesPortlet.REQUEST_SERVLET_PATH, viewId.replaceAll(".jsp", ".jsf"));
143             return null;
144         }
145 
146         UIViewRoot viewRoot = (UIViewRoot) request.getPortletSession().getAttribute(viewId,
147                 PortletSession.PORTLET_SCOPE);
148         if (null == viewRoot)
149         {
150             if (log.isDebugEnabled())
151             {
152                 log.debug("Creating new view root: " + viewId);
153             }
154             viewRoot = application.getViewHandler().createView(this, viewId);
155             //viewRoot = new UIViewRoot();
156             viewRoot.setViewId(viewId);
157             viewRoot.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
158             request.getPortletSession().setAttribute(viewId, viewRoot, PortletSession.PORTLET_SCOPE);
159         }
160         else
161         {
162             if (log.isDebugEnabled())
163             {
164                 log.debug("Using view root from session: " + viewId);
165             }
166         }
167         setViewRoot(viewRoot);
168         portletRequest.setAttribute(FacesPortlet.REQUEST_SERVLET_PATH, viewId.replaceAll(".jsp", ".jsf"));
169         return viewRoot;
170     }
171 
172     /***
173      * @see javax.faces.context.FacesContext#getExternalContext()
174      */
175     public ExternalContext getExternalContext()
176     {
177         return this.externalContext;
178     }
179 
180     /***
181      * @see javax.faces.context.FacesContext#getMaximumSeverity()
182      */
183     public FacesMessage.Severity getMaximumSeverity()
184     {
185         return this.maximumSeverity;
186     }
187 
188     /***
189      * @see javax.faces.context.FacesContext#getMessages()
190      */
191     public Iterator getMessages()
192     {
193         return (this.messages != null) ? this.messages.iterator() : Collections.EMPTY_LIST.iterator();
194     }
195 
196     /***
197      * @see javax.faces.context.FacesContext#getApplication()
198      */
199     public Application getApplication()
200     {
201         return this.application;
202     }
203 
204     /***
205      * @see javax.faces.context.FacesContext#getClientIdsWithMessages()
206      */
207     public Iterator getClientIdsWithMessages()
208     {
209         if (this.messages == null || this.messages.isEmpty())
210         {
211             return NullIterator.instance();
212         }
213 
214         return new Iterator()
215         {
216             private int next;
217 
218             boolean nextFound;
219 
220             public void remove()
221             {
222                 throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
223             }
224 
225             public boolean hasNext()
226             {
227                 if (!nextFound)
228                 {
229                     for (int len = messageClientIds.size(); next < len; next++)
230                     {
231                         if (messageClientIds.get(next) != NULL_DUMMY)
232                         {
233                             nextFound = true;
234                             break;
235                         }
236                     }
237                 }
238                 return nextFound;
239             }
240 
241             public Object next()
242             {
243                 if (hasNext())
244                 {
245                     nextFound = false;
246                     return messageClientIds.get(next++);
247                 }
248                 throw new NoSuchElementException();
249             }
250         };
251     }
252 
253     /***
254      * @see javax.faces.context.FacesContext#getMessages(java.lang.String)
255      */
256     public Iterator getMessages(String clientId)
257     {
258         if (this.messages == null)
259         {
260             return NullIterator.instance();
261         }
262 
263         List lst = new ArrayList();
264         for (int i = 0; i < this.messages.size(); i++)
265         {
266             Object savedClientId = this.messageClientIds.get(i);
267             if (clientId == null)
268             {
269                 if (savedClientId == NULL_DUMMY)
270                     lst.add(this.messages.get(i));
271             }
272             else
273             {
274                 if (clientId.equals(savedClientId))
275                     lst.add(this.messages.get(i));
276             }
277         }
278         return lst.iterator();
279     }
280 
281     /***
282      * @see javax.faces.context.FacesContext#getRenderKit()
283      */
284     public RenderKit getRenderKit()
285     {
286         if (getViewRoot() == null)
287         {
288             return null;
289         }
290 
291         String renderKitId = getViewRoot().getRenderKitId();
292 
293         if (renderKitId == null)
294         {
295             return null;
296         }
297 
298         return this.renderKitFactory.getRenderKit(this, renderKitId);
299     }
300 
301     /***
302      * @see javax.faces.context.FacesContext#getRenderResponse()
303      */
304     public boolean getRenderResponse()
305     {
306         return this.renderResponse;
307     }
308 
309     /***
310      * @see javax.faces.context.FacesContext#getResponseComplete()
311      */
312     public boolean getResponseComplete()
313     {
314         return this.responseComplete;
315     }
316 
317     /***
318      * @see javax.faces.context.FacesContext#setResponseStream(javax.faces.context.ResponseStream)
319      */
320     public void setResponseStream(ResponseStream responseStream)
321     {
322         if (responseStream == null)
323         {
324             throw new NullPointerException("responseStream");
325         }
326         this.responseStream = responseStream;
327     }
328 
329     /***
330      * @see javax.faces.context.FacesContext#getResponseStream()
331      */
332     public ResponseStream getResponseStream()
333     {
334         return this.responseStream;
335     }
336 
337     /***
338      * @see javax.faces.context.FacesContext#setResponseWriter(javax.faces.context.ResponseWriter)
339      */
340     public void setResponseWriter(ResponseWriter responseWriter)
341     {
342         if (responseWriter == null)
343         {
344             throw new NullPointerException("responseWriter");
345         }
346         this.responseWriter = responseWriter;
347     }
348 
349     /***
350      * @see javax.faces.context.FacesContext#getResponseWriter()
351      */
352     public ResponseWriter getResponseWriter()
353     {
354         return this.responseWriter;
355     }
356 
357     /***
358      * @see javax.faces.context.FacesContext#setViewRoot(javax.faces.component.UIViewRoot)
359      */
360     public void setViewRoot(UIViewRoot viewRoot)
361     {
362         if (viewRoot == null)
363         {
364             throw new NullPointerException("viewRoot");
365         }
366         this.viewRoot = viewRoot;
367     }
368 
369     /***
370      * @see javax.faces.context.FacesContext#getViewRoot()
371      */
372     public UIViewRoot getViewRoot()
373     {
374         return this.viewRoot;
375     }
376 
377     /***
378      * @see javax.faces.context.FacesContext#addMessage(java.lang.String,
379      *      javax.faces.application.FacesMessage)
380      */
381     public void addMessage(String clientId, FacesMessage message)
382     {
383         if (message == null)
384         {
385             throw new NullPointerException("message");
386         }
387 
388         if (this.messages == null)
389         {
390             this.messages = new ArrayList();
391             this.messageClientIds = new ArrayList();
392         }
393         this.messages.add(message);
394         this.messageClientIds.add((clientId != null) ? clientId : NULL_DUMMY);
395         FacesMessage.Severity serSeverity = message.getSeverity();
396         if (serSeverity != null && serSeverity.compareTo(this.maximumSeverity) > 0)
397         {
398             this.maximumSeverity = message.getSeverity();
399         }
400     }
401 
402     /***
403      * @see javax.faces.context.FacesContext#release()
404      */
405     public void release()
406     {
407         if (this.externalContext != null)
408         {
409             this.externalContext.release();
410             this.externalContext = null;
411         }
412 
413         this.messageClientIds = null;
414         this.messages = null;
415         this.application = null;
416         this.responseStream = null;
417         this.responseWriter = null;
418         this.viewRoot = null;
419 
420         FacesContext.setCurrentInstance(null);
421     }
422 
423     /***
424      * @see javax.faces.context.FacesContext#renderResponse()
425      */
426     public void renderResponse()
427     {
428         this.renderResponse = true;
429     }
430 
431     /***
432      * @see javax.faces.context.FacesContext#responseComplete()
433      */
434     public void responseComplete()
435     {
436         this.responseComplete = true;
437     }
438 }