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.List;
22  import java.util.ListIterator;
23  
24  import javax.faces.context.ExternalContext;
25  import javax.faces.context.FacesContext;
26  import javax.faces.context.FacesContextWrapper;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.myfaces.orchestra.frameworkAdapter.FrameworkAdapter;
31  
32  /**
33   * Convenient class to wrap the current FacesContext in portlet environment.
34   * 
35   * @since 1.4
36   * 
37   * @author Leonardo Uribe (latest modification by $Author: lu4242 $)
38   * @version $Revision: 798382 $ $Date: 2009-07-27 22:23:02 -0500 (lun, 27 jul 2009) $
39   */
40  public class _PortletFacesContextWrapper extends FacesContextWrapper
41  {
42      private final static String REQUEST_ADAPTER = "org.apache.myfaces.orchestra.REQUEST_ADAPTER";
43  
44      //~ Instance fields -------------------------------------------------------
45  
46      private final FacesContext _facesContext;
47      private final ExternalContext externalContextDelegate;
48      private final RequestHandler contextLockHandler;
49      private final List _handlers;
50      private final String _nextToken;
51  
52      private final Log log = LogFactory
53              .getLog(_PortletFacesContextWrapper.class);
54  
55      //~ Constructors ----------------------------------------------------------
56  
57      /**
58       * The install parameter controls whether this object will be configured as
59       * the object returned from calls to FacesContext.getCurrentInstance() or not.
60       * <p>
61       * When only overriding the release() method, then install=false is ok as that
62       * is called directly by the FacesServlet on the instance returned by the
63       * FacesContextFactory. However all other methods are invoked on the object
64       * that is returned from FacesContext.getCurrentInstance, so install=true is
65       * needed in order for any other method overrides to have any effect.
66       * <p>
67       * <b>IMPORTANT</b>: install=true should not be used until MYFACES-1820 is fixed.
68       */
69      public _PortletFacesContextWrapper(final FacesContext facesContext,
70              final boolean install, boolean finit, String fnextToken, List fhandlers,
71              final RequestHandler fcontextLockHandler )
72      {
73          if (log.isDebugEnabled())
74          {
75              log.debug("getFacesContext: running inner constructor");
76          }
77  
78          _facesContext = facesContext;
79  
80          if (install)
81          {
82              FacesContext.setCurrentInstance(this);
83          }
84  
85          externalContextDelegate = new PortletExternalContextWrapper(
86                  _facesContext.getExternalContext());
87  
88          _handlers = fhandlers;
89          _nextToken = fnextToken;
90          contextLockHandler = fcontextLockHandler;
91          if (finit)
92          {
93              ListIterator i = fhandlers.listIterator();
94              try
95              {
96                  contextLockHandler.init(facesContext);
97                  while (i.hasNext())
98                  {
99                      RequestHandler h = (RequestHandler) i.next();
100 
101                     if (log.isDebugEnabled())
102                     {
103                         log.debug("Running inithandler of type "
104                                 + h.getClass().getName());
105                     }
106 
107                     h.init(facesContext);
108                 }
109             }
110             catch (RuntimeException e)
111             {
112                 log.error("Problem initialising RequestHandler", e);
113                 _release(i);
114                 contextLockHandler.deinit();
115                 throw e;
116             }
117         }
118         else
119         {
120             try
121             {
122                 contextLockHandler.init(facesContext);
123             }
124             catch (RuntimeException e)
125             {
126                 contextLockHandler.deinit();
127             }
128 
129             RequestType type = ExternalContextUtils.getRequestType(facesContext
130                     .getExternalContext());
131 
132             if (RequestType.RENDER.equals(type))
133             {
134                 String handlersKey = (String) fnextToken;
135                 FrameworkAdapter adapter = (FrameworkAdapter) getExternalContext()
136                         .getApplicationMap().remove(
137                                 REQUEST_ADAPTER + handlersKey);
138                 if (FrameworkAdapter.getCurrentInstance() == null)
139                 {
140                     FrameworkAdapter.setCurrentInstance(adapter);
141                 }
142             }
143         }
144     }
145 
146     //~ Non-Final Methods -----------------------------------------------------
147 
148     public void release()
149     {
150         if (log.isDebugEnabled())
151         {
152             log.debug("Running release");
153         }
154         RequestType type = ExternalContextUtils
155                 .getRequestType(getExternalContext());
156         if (RequestType.RENDER.equals(type) || 
157             RequestType.EVENT.equals(type) || 
158             RequestType.RESOURCE.equals(type) || 
159             this.getResponseComplete())
160         {
161             ListIterator i = _handlers.listIterator();
162             while (i.hasNext())
163             {
164                 i.next();
165             }
166             _release(i);
167         }
168         if (RequestType.ACTION.equals(type))
169         {
170             if (this.getResponseComplete())
171             {
172                 // If response is complete by some reason, we need to
173                 // clean request handlers from application map. This is set
174                 // before an instance of this class is created.
175                 getExternalContext().getApplicationMap().remove(
176                         PortletOrchestraFacesContextFactory.REQUEST_HANDLERS+_nextToken);
177             }
178             else
179             {
180                 //Pass the current FrameworkAdapter through application map,
181                 //to remove it later when rendering 
182                 FrameworkAdapter adapter = FrameworkAdapter.getCurrentInstance();
183                 getExternalContext().getApplicationMap().put(
184                         REQUEST_ADAPTER + _nextToken, adapter);
185                 
186                 //Orchestra suppose the same thread handles the current request, but
187                 //in portlets this is not necessary true. One thread could handle action
188                 //requests and other render request. To keep code working we set it to
189                 //null here, so other request don't mix it.
190                 FrameworkAdapter.setCurrentInstance(null);
191             }
192         }
193 
194         try
195         {
196             //Since in portlets the same thread does not handler both action and
197             //render phase for the same request contextLockHandler needs to
198             //be cleared and lock again
199             contextLockHandler.deinit();
200         }
201         catch (Exception e)
202         {
203             log.error("Problem deinitialising RequestHandler", e);
204         }
205         if (log.isDebugEnabled())
206         {
207             log.debug("Release completed");
208         }
209         getWrapped().release();
210     }
211     
212     @Override
213     public FacesContext getWrapped()
214     {
215         return _facesContext;
216     }
217 
218     private void _release(ListIterator i)
219     {
220         while (i.hasPrevious())
221         {
222             try
223             {
224                 RequestHandler h = (RequestHandler) i.previous();
225                 if (log.isDebugEnabled())
226                 {
227                     log.debug("Running deinithandler of type "
228                             + h.getClass().getName());
229                 }
230                 h.deinit();
231             }
232             catch (Exception e)
233             {
234                 log.error("Problem deinitialising RequestHandler", e);
235             }
236         }
237     }
238 
239     //~ Final Methods ---------------------------------------------------------
240 
241     public ExternalContext getExternalContext()
242     {
243         return externalContextDelegate == null ? getWrapped()
244                 .getExternalContext() : externalContextDelegate;
245     }
246 }