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 }