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 }