View Javadoc

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