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          log.debug("getFacesContext: running inner constructor");
81  
82          _facesContext = facesContext;
83  
84          if (install)
85          {
86              FacesContext.setCurrentInstance(this);
87          }
88  
89          externalContextDelegate = new PortletExternalContextWrapper(
90                  _facesContext.getExternalContext());
91  
92          _handlers = fhandlers;
93          _nextToken = fnextToken;
94          contextLockHandler = fcontextLockHandler;
95          if (finit)
96          {
97              ListIterator i = fhandlers.listIterator();
98              try
99              {
100                 contextLockHandler.init(facesContext);
101                 while (i.hasNext())
102                 {
103                     RequestHandler h = (RequestHandler) i.next();
104 
105                     if (log.isDebugEnabled())
106                     {
107                         log.debug("Running inithandler of type "
108                                 + h.getClass().getName());
109                     }
110 
111                     h.init(facesContext);
112                 }
113             }
114             catch (RuntimeException e)
115             {
116                 log.error("Problem initialising RequestHandler", e);
117                 _release(i);
118                 contextLockHandler.deinit();
119                 throw e;
120             }
121         }
122         else
123         {
124             try
125             {
126                 contextLockHandler.init(facesContext);
127             }
128             catch (RuntimeException e)
129             {
130                 contextLockHandler.deinit();
131             }
132 
133             RequestType type = ExternalContextUtils.getRequestType(facesContext
134                     .getExternalContext());
135 
136             if (RequestType.RENDER.equals(type))
137             {
138                 String handlersKey = (String) fnextToken;
139                 FrameworkAdapter adapter = (FrameworkAdapter) getExternalContext()
140                         .getApplicationMap().remove(
141                                 REQUEST_ADAPTER + handlersKey);
142                 if (FrameworkAdapter.getCurrentInstance() == null)
143                 {
144                     FrameworkAdapter.setCurrentInstance(adapter);
145                 }
146             }
147         }
148     }
149 
150     //~ Non-Final Methods -----------------------------------------------------
151 
152     public void release()
153     {
154         log.debug("Running release");
155         RequestType type = ExternalContextUtils
156                 .getRequestType(getExternalContext());
157         if (RequestType.RENDER.equals(type) || 
158             RequestType.EVENT.equals(type) || 
159             RequestType.RESOURCE.equals(type) || 
160             this.getResponseComplete())
161         {
162             ListIterator i = _handlers.listIterator();
163             while (i.hasNext())
164             {
165                 i.next();
166             }
167             _release(i);
168         }
169         if (RequestType.ACTION.equals(type))
170         {
171             if (this.getResponseComplete())
172             {
173                 // If response is complete by some reason, we need to
174                 // clean request handlers from application map. This is set
175                 // before an instance of this class is created.
176                 getExternalContext().getApplicationMap().remove(
177                         PortletOrchestraFacesContextFactory.REQUEST_HANDLERS+_nextToken);
178             }
179             else
180             {
181                 //Pass the current FrameworkAdapter through application map,
182                 //to remove it later when rendering 
183                 FrameworkAdapter adapter = FrameworkAdapter.getCurrentInstance();
184                 getExternalContext().getApplicationMap().put(
185                         REQUEST_ADAPTER + _nextToken, adapter);
186                 
187                 //Orchestra suppose the same thread handles the current request, but
188                 //in portlets this is not necessary true. One thread could handle action
189                 //requests and other render request. To keep code working we set it to
190                 //null here, so other request don't mix it.
191                 FrameworkAdapter.setCurrentInstance(null);
192             }
193         }
194 
195         try
196         {
197             //Since in portlets the same thread does not handler both action and
198             //render phase for the same request contextLockHandler needs to
199             //be cleared and lock again
200             contextLockHandler.deinit();
201         }
202         catch (Exception e)
203         {
204             log.error("Problem deinitialising RequestHandler", e);
205         }
206         log.debug("Release completed");
207         _facesContext.release();
208     }
209 
210     private void _release(ListIterator i)
211     {
212         while (i.hasPrevious())
213         {
214             try
215             {
216                 RequestHandler h = (RequestHandler) i.previous();
217                 if (log.isDebugEnabled())
218                 {
219                     log.debug("Running deinithandler of type "
220                             + h.getClass().getName());
221                 }
222                 h.deinit();
223             }
224             catch (Exception e)
225             {
226                 log.error("Problem deinitialising RequestHandler", e);
227             }
228         }
229     }
230 
231     //~ Final Methods ---------------------------------------------------------
232 
233     public final Application getApplication()
234     {
235         return _facesContext.getApplication();
236     }
237 
238     public final Iterator getClientIdsWithMessages()
239     {
240         return _facesContext.getClientIdsWithMessages();
241     }
242 
243     public ExternalContext getExternalContext()
244     {
245         return externalContextDelegate == null ? _facesContext
246                 .getExternalContext() : externalContextDelegate;
247     }
248 
249     public final FacesMessage.Severity getMaximumSeverity()
250     {
251         return _facesContext.getMaximumSeverity();
252     }
253 
254     public final Iterator getMessages()
255     {
256         return _facesContext.getMessages();
257     }
258 
259     public final Iterator getMessages(String clientId)
260     {
261         return _facesContext.getMessages(clientId);
262     }
263 
264     public final RenderKit getRenderKit()
265     {
266         return _facesContext.getRenderKit();
267     }
268 
269     public final boolean getRenderResponse()
270     {
271         return _facesContext.getRenderResponse();
272     }
273 
274     public final boolean getResponseComplete()
275     {
276         return _facesContext.getResponseComplete();
277     }
278 
279     public final void setResponseStream(ResponseStream responsestream)
280     {
281         _facesContext.setResponseStream(responsestream);
282     }
283 
284     public final ResponseStream getResponseStream()
285     {
286         return _facesContext.getResponseStream();
287     }
288 
289     public final void setResponseWriter(ResponseWriter responsewriter)
290     {
291         _facesContext.setResponseWriter(responsewriter);
292     }
293 
294     public final ResponseWriter getResponseWriter()
295     {
296         return _facesContext.getResponseWriter();
297     }
298 
299     public final void setViewRoot(UIViewRoot viewRoot)
300     {
301         _facesContext.setViewRoot(viewRoot);
302     }
303 
304     public final UIViewRoot getViewRoot()
305     {
306         return _facesContext.getViewRoot();
307     }
308 
309     public final void addMessage(String clientId, FacesMessage message)
310     {
311         _facesContext.addMessage(clientId, message);
312     }
313 
314     public final void renderResponse()
315     {
316         _facesContext.renderResponse();
317     }
318 
319     public final void responseComplete()
320     {
321         _facesContext.responseComplete();
322     }
323 
324     public final ELContext getELContext()
325     {
326         return _facesContext.getELContext();
327     }
328 }