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          log.debug("getFacesContext: running inner constructor");
74  
75          _facesContext = facesContext;
76  
77          if (install)
78          {
79              FacesContext.setCurrentInstance(this);
80          }
81  
82          externalContextDelegate = new PortletExternalContextWrapper(
83                  _facesContext.getExternalContext());
84  
85          _handlers = fhandlers;
86          _nextToken = fnextToken;
87          contextLockHandler = fcontextLockHandler;
88          if (finit)
89          {
90              ListIterator i = fhandlers.listIterator();
91              try
92              {
93                  contextLockHandler.init(facesContext);
94                  while (i.hasNext())
95                  {
96                      RequestHandler h = (RequestHandler) i.next();
97  
98                      if (log.isDebugEnabled())
99                      {
100                         log.debug("Running inithandler of type "
101                                 + h.getClass().getName());
102                     }
103 
104                     h.init(facesContext);
105                 }
106             }
107             catch (RuntimeException e)
108             {
109                 log.error("Problem initialising RequestHandler", e);
110                 _release(i);
111                 contextLockHandler.deinit();
112                 throw e;
113             }
114         }
115         else
116         {
117             try
118             {
119                 contextLockHandler.init(facesContext);
120             }
121             catch (RuntimeException e)
122             {
123                 contextLockHandler.deinit();
124             }
125 
126             RequestType type = ExternalContextUtils.getRequestType(facesContext
127                     .getExternalContext());
128 
129             if (RequestType.RENDER.equals(type))
130             {
131                 String handlersKey = (String) fnextToken;
132                 FrameworkAdapter adapter = (FrameworkAdapter) getExternalContext()
133                         .getApplicationMap().remove(
134                                 REQUEST_ADAPTER + handlersKey);
135                 if (FrameworkAdapter.getCurrentInstance() == null)
136                 {
137                     FrameworkAdapter.setCurrentInstance(adapter);
138                 }
139             }
140         }
141     }
142 
143     //~ Non-Final Methods -----------------------------------------------------
144 
145     public void release()
146     {
147         log.debug("Running release");
148         RequestType type = ExternalContextUtils
149                 .getRequestType(getExternalContext());
150         if (RequestType.RENDER.equals(type) || 
151             RequestType.EVENT.equals(type) || 
152             RequestType.RESOURCE.equals(type) || 
153             this.getResponseComplete())
154         {
155             ListIterator i = _handlers.listIterator();
156             while (i.hasNext())
157             {
158                 i.next();
159             }
160             _release(i);
161         }
162         if (RequestType.ACTION.equals(type))
163         {
164             if (this.getResponseComplete())
165             {
166                 // If response is complete by some reason, we need to
167                 // clean request handlers from application map. This is set
168                 // before an instance of this class is created.
169                 getExternalContext().getApplicationMap().remove(
170                         PortletOrchestraFacesContextFactory.REQUEST_HANDLERS+_nextToken);
171             }
172             else
173             {
174                 //Pass the current FrameworkAdapter through application map,
175                 //to remove it later when rendering 
176                 FrameworkAdapter adapter = FrameworkAdapter.getCurrentInstance();
177                 getExternalContext().getApplicationMap().put(
178                         REQUEST_ADAPTER + _nextToken, adapter);
179                 
180                 //Orchestra suppose the same thread handles the current request, but
181                 //in portlets this is not necessary true. One thread could handle action
182                 //requests and other render request. To keep code working we set it to
183                 //null here, so other request don't mix it.
184                 FrameworkAdapter.setCurrentInstance(null);
185             }
186         }
187 
188         try
189         {
190             //Since in portlets the same thread does not handler both action and
191             //render phase for the same request contextLockHandler needs to
192             //be cleared and lock again
193             contextLockHandler.deinit();
194         }
195         catch (Exception e)
196         {
197             log.error("Problem deinitialising RequestHandler", e);
198         }
199         log.debug("Release completed");
200         getWrapped().release();
201     }
202     
203     @Override
204     public FacesContext getWrapped()
205     {
206         return _facesContext;
207     }
208 
209     private void _release(ListIterator i)
210     {
211         while (i.hasPrevious())
212         {
213             try
214             {
215                 RequestHandler h = (RequestHandler) i.previous();
216                 if (log.isDebugEnabled())
217                 {
218                     log.debug("Running deinithandler of type "
219                             + h.getClass().getName());
220                 }
221                 h.deinit();
222             }
223             catch (Exception e)
224             {
225                 log.error("Problem deinitialising RequestHandler", e);
226             }
227         }
228     }
229 
230     //~ Final Methods ---------------------------------------------------------
231 
232     public ExternalContext getExternalContext()
233     {
234         return externalContextDelegate == null ? getWrapped()
235                 .getExternalContext() : externalContextDelegate;
236     }
237 }