View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.orchestra.lib.jsf;
20  
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.ListIterator;
24  
25  import javax.el.ELContext;
26  import javax.faces.application.Application;
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  
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  import org.apache.myfaces.orchestra.frameworkAdapter.FrameworkAdapter;
38  
39  /**
40   * Convenient class to wrap the current FacesContext in portlet environment.
41   * 
42   * @since 1.4
43   * 
44   * @author Leonardo Uribe (latest modification by $Author: lu4242 $)
45   * @version $Revision: 798382 $ $Date: 2009-07-27 22:23:02 -0500 (lun, 27 jul 2009) $
46   */
47  public class _PortletFacesContextWrapper extends FacesContext
48  {
49      private final static String REQUEST_ADAPTER = "org.apache.myfaces.orchestra.REQUEST_ADAPTER";
50  
51      //~ Instance fields -------------------------------------------------------
52  
53      private final FacesContext _facesContext;
54      private final ExternalContext externalContextDelegate;
55      private final RequestHandler contextLockHandler;
56      private final List _handlers;
57      private final String _nextToken;
58  
59      private final Log log = LogFactory
60              .getLog(_PortletFacesContextWrapper.class);
61  
62      //~ Constructors ----------------------------------------------------------
63  
64      /**
65       * The install parameter controls whether this object will be configured as
66       * the object returned from calls to FacesContext.getCurrentInstance() or not.
67       * <p>
68       * When only overriding the release() method, then install=false is ok as that
69       * is called directly by the FacesServlet on the instance returned by the
70       * FacesContextFactory. However all other methods are invoked on the object
71       * that is returned from FacesContext.getCurrentInstance, so install=true is
72       * needed in order for any other method overrides to have any effect.
73       * <p>
74       * <b>IMPORTANT</b>: install=true should not be used until MYFACES-1820 is fixed.
75       */
76      public _PortletFacesContextWrapper(final FacesContext facesContext,
77              final boolean install, boolean finit, String fnextToken, List fhandlers,
78              final RequestHandler fcontextLockHandler )
79      {
80          if (log.isDebugEnabled())
81          {
82              log.debug("getFacesContext: running inner constructor");
83          }
84  
85          _facesContext = facesContext;
86  
87          if (install)
88          {
89              FacesContext.setCurrentInstance(this);
90          }
91  
92          externalContextDelegate = new PortletExternalContextWrapper(
93                  _facesContext.getExternalContext());
94  
95          _handlers = fhandlers;
96          _nextToken = fnextToken;
97          contextLockHandler = fcontextLockHandler;
98          if (finit)
99          {
100             ListIterator i = fhandlers.listIterator();
101             try
102             {
103                 contextLockHandler.init(facesContext);
104                 while (i.hasNext())
105                 {
106                     RequestHandler h = (RequestHandler) i.next();
107 
108                     if (log.isDebugEnabled())
109                     {
110                         log.debug("Running inithandler of type "
111                                 + h.getClass().getName());
112                     }
113 
114                     h.init(facesContext);
115                 }
116             }
117             catch (RuntimeException e)
118             {
119                 log.error("Problem initialising RequestHandler", e);
120                 _release(i);
121                 contextLockHandler.deinit();
122                 throw e;
123             }
124         }
125         else
126         {
127             try
128             {
129                 contextLockHandler.init(facesContext);
130             }
131             catch (RuntimeException e)
132             {
133                 contextLockHandler.deinit();
134             }
135 
136             RequestType type = ExternalContextUtils.getRequestType(facesContext
137                     .getExternalContext());
138 
139             if (RequestType.RENDER.equals(type))
140             {
141                 String handlersKey = (String) fnextToken;
142                 FrameworkAdapter adapter = (FrameworkAdapter) getExternalContext()
143                         .getApplicationMap().remove(
144                                 REQUEST_ADAPTER + handlersKey);
145                 if (FrameworkAdapter.getCurrentInstance() == null)
146                 {
147                     FrameworkAdapter.setCurrentInstance(adapter);
148                 }
149             }
150         }
151     }
152 
153     //~ Non-Final Methods -----------------------------------------------------
154 
155     public void release()
156     {
157         if (log.isDebugEnabled())
158         {
159             log.debug("Running release");
160         }
161         RequestType type = ExternalContextUtils
162                 .getRequestType(getExternalContext());
163         if (RequestType.RENDER.equals(type) || 
164             RequestType.EVENT.equals(type) || 
165             RequestType.RESOURCE.equals(type) || 
166             this.getResponseComplete())
167         {
168             ListIterator i = _handlers.listIterator();
169             while (i.hasNext())
170             {
171                 i.next();
172             }
173             _release(i);
174         }
175         if (RequestType.ACTION.equals(type))
176         {
177             if (this.getResponseComplete())
178             {
179                 // If response is complete by some reason, we need to
180                 // clean request handlers from application map. This is set
181                 // before an instance of this class is created.
182                 getExternalContext().getApplicationMap().remove(
183                         PortletOrchestraFacesContextFactory.REQUEST_HANDLERS+_nextToken);
184             }
185             else
186             {
187                 //Pass the current FrameworkAdapter through application map,
188                 //to remove it later when rendering 
189                 FrameworkAdapter adapter = FrameworkAdapter.getCurrentInstance();
190                 getExternalContext().getApplicationMap().put(
191                         REQUEST_ADAPTER + _nextToken, adapter);
192                 
193                 //Orchestra suppose the same thread handles the current request, but
194                 //in portlets this is not necessary true. One thread could handle action
195                 //requests and other render request. To keep code working we set it to
196                 //null here, so other request don't mix it.
197                 FrameworkAdapter.setCurrentInstance(null);
198             }
199         }
200 
201         try
202         {
203             //Since in portlets the same thread does not handler both action and
204             //render phase for the same request contextLockHandler needs to
205             //be cleared and lock again
206             contextLockHandler.deinit();
207         }
208         catch (Exception e)
209         {
210             log.error("Problem deinitialising RequestHandler", e);
211         }
212         if (log.isDebugEnabled())
213         {
214             log.debug("Release completed");
215         }
216         _facesContext.release();
217     }
218 
219     private void _release(ListIterator i)
220     {
221         while (i.hasPrevious())
222         {
223             try
224             {
225                 RequestHandler h = (RequestHandler) i.previous();
226                 if (log.isDebugEnabled())
227                 {
228                     log.debug("Running deinithandler of type "
229                             + h.getClass().getName());
230                 }
231                 h.deinit();
232             }
233             catch (Exception e)
234             {
235                 log.error("Problem deinitialising RequestHandler", e);
236             }
237         }
238     }
239 
240     //~ Final Methods ---------------------------------------------------------
241 
242     public final Application getApplication()
243     {
244         return _facesContext.getApplication();
245     }
246 
247     public final Iterator getClientIdsWithMessages()
248     {
249         return _facesContext.getClientIdsWithMessages();
250     }
251 
252     public ExternalContext getExternalContext()
253     {
254         return externalContextDelegate == null ? _facesContext
255                 .getExternalContext() : externalContextDelegate;
256     }
257 
258     public final FacesMessage.Severity getMaximumSeverity()
259     {
260         return _facesContext.getMaximumSeverity();
261     }
262 
263     public final Iterator getMessages()
264     {
265         return _facesContext.getMessages();
266     }
267 
268     public final Iterator getMessages(String clientId)
269     {
270         return _facesContext.getMessages(clientId);
271     }
272 
273     public final RenderKit getRenderKit()
274     {
275         return _facesContext.getRenderKit();
276     }
277 
278     public final boolean getRenderResponse()
279     {
280         return _facesContext.getRenderResponse();
281     }
282 
283     public final boolean getResponseComplete()
284     {
285         return _facesContext.getResponseComplete();
286     }
287 
288     public final void setResponseStream(ResponseStream responsestream)
289     {
290         _facesContext.setResponseStream(responsestream);
291     }
292 
293     public final ResponseStream getResponseStream()
294     {
295         return _facesContext.getResponseStream();
296     }
297 
298     public final void setResponseWriter(ResponseWriter responsewriter)
299     {
300         _facesContext.setResponseWriter(responsewriter);
301     }
302 
303     public final ResponseWriter getResponseWriter()
304     {
305         return _facesContext.getResponseWriter();
306     }
307 
308     public final void setViewRoot(UIViewRoot viewRoot)
309     {
310         _facesContext.setViewRoot(viewRoot);
311     }
312 
313     public final UIViewRoot getViewRoot()
314     {
315         return _facesContext.getViewRoot();
316     }
317 
318     public final void addMessage(String clientId, FacesMessage message)
319     {
320         _facesContext.addMessage(clientId, message);
321     }
322 
323     public final void renderResponse()
324     {
325         _facesContext.renderResponse();
326     }
327 
328     public final void responseComplete()
329     {
330         _facesContext.responseComplete();
331     }
332 
333     public final ELContext getELContext()
334     {
335         return _facesContext.getELContext();
336     }
337 }