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         String requestType = (String)portletRequest.getAttribute(FacesPortlet.REQUEST_TYPE); 
136         if (requestType != null && requestType.equals(FacesPortlet.ACTION_REQUEST))
137         {
138             if (log.isDebugEnabled())
139             {
140                 log.debug("Resolving action: " + viewId);
141             }
142             setViewRoot(viewRoot);
143             portletRequest.setAttribute(FacesPortlet.REQUEST_SERVLET_PATH, viewId.replaceAll(".jsp", ".jsf"));
144             return null;
145         }
146 
147         UIViewRoot viewRoot = (UIViewRoot) request.getPortletSession().getAttribute(viewId,
148                 PortletSession.PORTLET_SCOPE);
149         if (null == viewRoot)
150         {
151             if (log.isDebugEnabled())
152             {
153                 log.debug("Creating new view root: " + viewId);
154             }
155             viewRoot = application.getViewHandler().createView(this, viewId);
156             //viewRoot = new UIViewRoot();
157             UIViewRoot newViewRoot = new PortletUIViewRoot(viewRoot);
158             viewRoot = newViewRoot;
159             viewRoot.setViewId(viewId);
160             viewRoot.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
161             request.getPortletSession().setAttribute(viewId, viewRoot, PortletSession.PORTLET_SCOPE);
162         }
163         else
164         {
165             if (log.isDebugEnabled())
166             {
167                 log.debug("Using view root from session: " + viewId);
168             }
169         }
170         setViewRoot(viewRoot);
171         portletRequest.setAttribute(FacesPortlet.REQUEST_SERVLET_PATH, viewId.replaceAll(".jsp", ".jsf"));
172         return viewRoot;
173     }
174 
175     /***
176      * @see javax.faces.context.FacesContext#getExternalContext()
177      */
178     public ExternalContext getExternalContext()
179     {
180         return this.externalContext;
181     }
182 
183     /***
184      * @see javax.faces.context.FacesContext#getMaximumSeverity()
185      */
186     public FacesMessage.Severity getMaximumSeverity()
187     {
188         return this.maximumSeverity;
189     }
190 
191     /***
192      * @see javax.faces.context.FacesContext#getMessages()
193      */
194     public Iterator getMessages()
195     {
196         return (this.messages != null) ? this.messages.iterator() : Collections.EMPTY_LIST.iterator();
197     }
198 
199     /***
200      * @see javax.faces.context.FacesContext#getApplication()
201      */
202     public Application getApplication()
203     {
204         return this.application;
205     }
206 
207     /***
208      * @see javax.faces.context.FacesContext#getClientIdsWithMessages()
209      */
210     public Iterator getClientIdsWithMessages()
211     {
212         if (this.messages == null || this.messages.isEmpty())
213         {
214             return NullIterator.instance();
215         }
216 
217         return new Iterator()
218         {
219             private int next;
220 
221             boolean nextFound;
222 
223             public void remove()
224             {
225                 throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
226             }
227 
228             public boolean hasNext()
229             {
230                 if (!nextFound)
231                 {
232                     for (int len = messageClientIds.size(); next < len; next++)
233                     {
234                         if (messageClientIds.get(next) != NULL_DUMMY)
235                         {
236                             nextFound = true;
237                             break;
238                         }
239                     }
240                 }
241                 return nextFound;
242             }
243 
244             public Object next()
245             {
246                 if (hasNext())
247                 {
248                     nextFound = false;
249                     return messageClientIds.get(next++);
250                 }
251                 throw new NoSuchElementException();
252             }
253         };
254     }
255 
256     /***
257      * @see javax.faces.context.FacesContext#getMessages(java.lang.String)
258      */
259     public Iterator getMessages(String clientId)
260     {
261         if (this.messages == null)
262         {
263             return NullIterator.instance();
264         }
265 
266         List lst = new ArrayList();
267         for (int i = 0; i < this.messages.size(); i++)
268         {
269             Object savedClientId = this.messageClientIds.get(i);
270             if (clientId == null)
271             {
272                 if (savedClientId == NULL_DUMMY)
273                     lst.add(this.messages.get(i));
274             }
275             else
276             {
277                 if (clientId.equals(savedClientId))
278                     lst.add(this.messages.get(i));
279             }
280         }
281         return lst.iterator();
282     }
283 
284     /***
285      * @see javax.faces.context.FacesContext#getRenderKit()
286      */
287     public RenderKit getRenderKit()
288     {
289         if (getViewRoot() == null)
290         {
291             return null;
292         }
293 
294         String renderKitId = getViewRoot().getRenderKitId();
295 
296         if (renderKitId == null)
297         {
298             return null;
299         }
300 
301         return this.renderKitFactory.getRenderKit(this, renderKitId);
302     }
303 
304     /***
305      * @see javax.faces.context.FacesContext#getRenderResponse()
306      */
307     public boolean getRenderResponse()
308     {
309         return this.renderResponse;
310     }
311 
312     /***
313      * @see javax.faces.context.FacesContext#getResponseComplete()
314      */
315     public boolean getResponseComplete()
316     {
317         return this.responseComplete;
318     }
319 
320     /***
321      * @see javax.faces.context.FacesContext#setResponseStream(javax.faces.context.ResponseStream)
322      */
323     public void setResponseStream(ResponseStream responseStream)
324     {
325         if (responseStream == null)
326         {
327             throw new NullPointerException("responseStream");
328         }
329         this.responseStream = responseStream;
330     }
331 
332     /***
333      * @see javax.faces.context.FacesContext#getResponseStream()
334      */
335     public ResponseStream getResponseStream()
336     {
337         return this.responseStream;
338     }
339 
340     /***
341      * @see javax.faces.context.FacesContext#setResponseWriter(javax.faces.context.ResponseWriter)
342      */
343     public void setResponseWriter(ResponseWriter responseWriter)
344     {
345         if (responseWriter == null)
346         {
347             throw new NullPointerException("responseWriter");
348         }
349         this.responseWriter = responseWriter;
350     }
351 
352     /***
353      * @see javax.faces.context.FacesContext#getResponseWriter()
354      */
355     public ResponseWriter getResponseWriter()
356     {
357         return this.responseWriter;
358     }
359 
360     /***
361      * @see javax.faces.context.FacesContext#setViewRoot(javax.faces.component.UIViewRoot)
362      */
363     public void setViewRoot(UIViewRoot viewRoot)
364     {
365         if (viewRoot == null)
366         {
367             throw new NullPointerException("viewRoot");
368         }
369         this.viewRoot = viewRoot;
370     }
371 
372     /***
373      * @see javax.faces.context.FacesContext#getViewRoot()
374      */
375     public UIViewRoot getViewRoot()
376     {
377         return this.viewRoot;
378     }
379 
380     /***
381      * @see javax.faces.context.FacesContext#addMessage(java.lang.String,
382      *      javax.faces.application.FacesMessage)
383      */
384     public void addMessage(String clientId, FacesMessage message)
385     {
386         if (message == null)
387         {
388             throw new NullPointerException("message");
389         }
390 
391         if (this.messages == null)
392         {
393             this.messages = new ArrayList();
394             this.messageClientIds = new ArrayList();
395         }
396         this.messages.add(message);
397         this.messageClientIds.add((clientId != null) ? clientId : NULL_DUMMY);
398         FacesMessage.Severity serSeverity = message.getSeverity();
399         if (serSeverity != null && serSeverity.compareTo(this.maximumSeverity) > 0)
400         {
401             this.maximumSeverity = message.getSeverity();
402         }
403     }
404 
405     /***
406      * @see javax.faces.context.FacesContext#release()
407      */
408     public void release()
409     {
410         if (this.externalContext != null)
411         {
412             this.externalContext.release();
413             this.externalContext = null;
414         }
415 
416         this.messageClientIds = null;
417         this.messages = null;
418         this.application = null;
419         this.responseStream = null;
420         this.responseWriter = null;
421         this.viewRoot = null;
422 
423         FacesContext.setCurrentInstance(null);
424     }
425 
426     /***
427      * @see javax.faces.context.FacesContext#renderResponse()
428      */
429     public void renderResponse()
430     {
431         this.renderResponse = true;
432     }
433 
434     /***
435      * @see javax.faces.context.FacesContext#responseComplete()
436      */
437     public void responseComplete()
438     {
439         this.responseComplete = true;
440     }
441 }