You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mf...@apache.org on 2011/05/26 23:29:20 UTC

svn commit: r1128097 [2/5] - in /myfaces/portlet-bridge/core/branches/refactored_3.0.x: controller-api/src/main/java/org/apache/myfaces/portlet/faces/bridge/ impl/src/main/java/org/apache/myfaces/portlet/faces/application/ impl/src/main/java/org/apache...

Modified: myfaces/portlet-bridge/core/branches/refactored_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/branches/refactored_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java?rev=1128097&r1=1128096&r2=1128097&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/branches/refactored_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java (original)
+++ myfaces/portlet-bridge/core/branches/refactored_3.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java Thu May 26 21:29:19 2011
@@ -19,76 +19,27 @@
 
 package org.apache.myfaces.portlet.faces.bridge;
 
-import java.io.IOException;
-import java.io.Serializable;
-
-import java.lang.reflect.Method;
-
-import java.net.URL;
-
-import java.rmi.server.UID;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.ListIterator;
-import java.util.Locale;
 import java.util.Map;
-import java.util.Set;
-
-import java.util.Vector;
 
-import javax.el.ELContext;
-import javax.el.ELContextEvent;
-import javax.el.ELContextListener;
-import javax.el.ValueExpression;
-import javax.faces.FacesException;
-import javax.faces.FactoryFinder;
-import javax.faces.application.Application;
-import javax.faces.application.ApplicationFactory;
-import javax.faces.application.FacesMessage;
-import javax.faces.application.StateManager;
-import javax.faces.application.ViewHandler;
-import javax.faces.component.UIViewRoot;
-import javax.faces.context.ExceptionHandler;
-import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
-import javax.faces.context.FacesContextFactory;
-import javax.faces.event.AbortProcessingException;
-import javax.faces.event.PhaseEvent;
-import javax.faces.event.PhaseId;
-import javax.faces.event.PhaseListener;
-import javax.faces.event.PostConstructApplicationEvent;
 import javax.faces.event.SystemEvent;
-import javax.faces.event.SystemEventListener;
-import javax.faces.lifecycle.Lifecycle;
-import javax.faces.lifecycle.LifecycleFactory;
-import javax.faces.render.ResponseStateManager;
-import javax.faces.webapp.FacesServlet;
+
 import javax.portlet.ActionRequest;
 import javax.portlet.ActionResponse;
 import javax.portlet.EventRequest;
 import javax.portlet.EventResponse;
-import javax.portlet.MimeResponse;
-import javax.portlet.PortalContext;
 import javax.portlet.PortletConfig;
 import javax.portlet.PortletContext;
-import javax.portlet.PortletException;
-import javax.portlet.PortletPreferences;
 import javax.portlet.PortletRequest;
-import javax.portlet.PortletRequestDispatcher;
 import javax.portlet.PortletResponse;
-import javax.portlet.PortletSession;
 import javax.portlet.RenderRequest;
 import javax.portlet.RenderResponse;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
-import javax.portlet.StateAwareResponse;
-import javax.portlet.filter.PortletResponseWrapper;
+
 import javax.portlet.faces.Bridge;
 import javax.portlet.faces.BridgeDefaultViewNotSpecifiedException;
 import javax.portlet.faces.BridgeEventHandler;
@@ -96,98 +47,26 @@ import javax.portlet.faces.BridgeExcepti
 import javax.portlet.faces.BridgeNotAFacesRequestException;
 import javax.portlet.faces.BridgePublicRenderParameterHandler;
 import javax.portlet.faces.BridgeUninitializedException;
-import javax.portlet.faces.BridgeUtil;
 import javax.portlet.faces.BridgeWriteBehindResponse;
-import javax.portlet.faces.annotation.BridgePreDestroy;
-import javax.portlet.faces.annotation.BridgeRequestScopeAttributeAdded;
-import javax.portlet.faces.annotation.ExcludeFromManagedRequestScope;
-
-import javax.portlet.faces.event.EventNavigationResult;
-
-import javax.portlet.filter.PortletResponseWrapper;
-import javax.portlet.filter.RenderResponseWrapper;
-
-import javax.portlet.filter.ResourceResponseWrapper;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletRequestAttributeEvent;
-import javax.servlet.ServletRequestAttributeListener;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionActivationListener;
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-
-import javax.servlet.http.HttpSessionEvent;
-
-import org.apache.myfaces.portlet.faces.application.PortletStateManagerImpl;
-import org.apache.myfaces.portlet.faces.bridge.wrapper.BridgePortletRequestWrapper;
-import org.apache.myfaces.portlet.faces.bridge.wrapper.BridgeRenderRequestWrapper;
-import org.apache.myfaces.portlet.faces.context.PortletExceptionHanderFactoryImpl;
-import org.apache.myfaces.portlet.faces.context.PortletExternalContextImpl;
-import org.apache.myfaces.portlet.faces.el.PortletELContextImpl;
-import org.apache.myfaces.portlet.faces.el.PortletELResolver;
-import org.apache.myfaces.portlet.faces.util.QueryString;
+
+import org.apache.myfaces.portlet.faces.bridge.config.BridgeConfigImpl;
+import org.apache.myfaces.portlet.faces.bridge.context.BridgeContextImpl;
+import org.apache.myfaces.portlet.faces.bridge.context.PreFacesFacesContext;
+
+import org.apache.myfaces.portlet.faces.bridge.controller.BridgeControllerImpl;
 import org.apache.myfaces.portlet.faces.util.config.FacesConfigurationProcessor;
 import org.apache.myfaces.portlet.faces.util.config.WebConfigurationProcessor;
 
+//import org.apache.myfaces.portlet.faces.bridge.controller.BridgeControllerImpl;
+
+
 public class BridgeImpl
-  implements Bridge, ELContextListener, PhaseListener, ServletRequestAttributeListener, SystemEventListener
+  implements Bridge
 {
-  private static final long serialVersionUID = 5807626987246270989L;
-
-  // public so PortletStateManager/ViewHandler/ExternalContext can see/use
-  public static final String UPDATED_VIEW_STATE_PARAM = "org.apache.myfaces.portlet.faces.updatedViewStateParam";
-  public static final String REDIRECT_VIEWPARAMS = "org.apache.myfaces.portlet.faces.redirectViewParams";
-  public static final String RENDER_REDIRECT_VIEWPARAMS = "org.apache.myfaces.portlet.faces.renderRedirectViewParams";
-  public static final String RENDER_REDIRECT_PRPMAP = "org.apache.myfaces.portlet.faces.renderRedirectPRPMap";
-  public static final String HAS_RENDER_REDIRECTED_AFTER_FORWARD = "org.apache.myfaces.portlet.faces.hasRenderRedirectedAfterForward";
-  public static final String LOGGING_ENABLED = "org.apache.myfaces.portlet.faces.loggingEnabled";
-  public static final String WRITE_BEHIND_RESPONSE = "org.apache.myfaces.portlet.faces.writeBehindResponse";
-  
-  // public so other parts of the impl can access the portletName to access portlet specific context attrs
-  public static final String PORTLET_NAME_ATTRIBUTE = "org.apache.myfaces.portlet.faces.portletName";
-  public static final String VIEWID_QUERYSTRING_ATTRIBUTE = "org.apache.myfaces.portlet.faces.viewIdQueryString";
-
-  private static final String FACES_CONTEXT_SCOPE = "org.apache.myfaces.portlet.faces.includeInScope.facesContextScope";
-  private static final String REQUEST_SCOPE_LOCK = "org.apache.myfaces.portlet.faces.requestScopeLock";
-  private static final String REQUEST_SCOPE_MAP = "org.apache.myfaces.portlet.faces.requestScopeMap";
-  private static final String SCOPE_VIEW_KEY = "org.apache.myfaces.portlet.faces.includeInScope.scopeViewKey";
-  private static final String CHILD_RESOURCE_REQUEST_SCOPE_MAP = "org.apache.myfaces.portlet.faces.includeInScope.childResourceRequestScopeMap";
-  private static final String REQUEST_SCOPE_LISTENER = "org.apache.myfaces.portlet.faces.requestScopeWatch";
-  public static final String FACES_VIEWROOT = "org.apache.myfaces.portlet.faces.includeInScope.facesViewRoot";
-  private static final String FACES_MESSAGES = "org.apache.myfaces.portlet.faces.includeInScope.facesMessages";
-  public static final String REQUEST_PARAMETERS = "org.apache.myfaces.portlet.faces.includeInScope.requestParameters";
-  public static final String PREEXISTING_ATTRIBUTE_NAMES = "org.apache.myfaces.portlet.faces.preExistingAttributeNames";
-  private static final String REQUEST_SCOPE_ID_RENDER_PARAM = "__jpfbReqScopeId";
-  private static final String NULL_VIEW_STATE_PARAM_VALUE = "org.apache.myfaces.portlet.faces.nullViewState";
-  private static final String CACHED_VIEWROOT_LOCALE = "org.apache.myfaces.portlet.faces.cachedViewRootLocale";
-  private static final String PROCESSED_PUBLIC_PARAMS ="org.apache.myfaces.portlet.faces.processedPublicParams";
-  public static final String SAVED_VIEW_STATE = "org.apache.myfaces.portlet.faces.includeInScope.saveViewState";
-
-  private static final int DEFAULT_MAX_MANAGED_REQUEST_SCOPES = 100;
-
-  private Boolean mPreserveActionParams = Boolean.FALSE;
-  private List<String> mExcludedRequestAttributes = null;
-  private Map<String, String>mPublicParameterMappings = null;
-
-  private PortletConfig mPortletConfig = null;
-  private FacesContextFactory mFacesContextFactory = null;
-  private Lifecycle mLifecycle = null;
-  private BridgeEventHandler mEventHandler = null; 
-  private BridgePublicRenderParameterHandler mProcessPRPHandler = null;
-  private List<String> mFacesMappings = null;
-  private List<String> mPreservedFacesContextScopeAttrs = null;
+  private BridgeConfig mBridgeConfig = null;
+  private BridgeController mBridgeController = null;
   private boolean mInitialized = false;
-  private Boolean mDebugLoggingEnabled;
-
-  private Map<String,String> mDefaultViewIdMap = null;
   
-  private Class<? extends BridgeWriteBehindResponse> mWriteBehindRenderResponseWrapper = null;
-  private Class<? extends BridgeWriteBehindResponse> mWriteBehindResourceResponseWrapper = null;
-
   public BridgeImpl()
   {
     // everything gets done in the init call.
@@ -199,378 +78,223 @@ public class BridgeImpl
     //TODO: Should we throw an exception if the bridge is already initialized?
     if (mInitialized)
       throw new BridgeException("Bridge already initialized.");
-
-    mPortletConfig = config;
-    PortletContext portletContext = mPortletConfig.getPortletContext();
     
-    // See if the bridge should log informational messages
-    mDebugLoggingEnabled = (Boolean) portletContext.getAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + mPortletConfig.getPortletName() + 
-                                              "." + BridgeImpl.LOGGING_ENABLED);
-    if (mDebugLoggingEnabled == null)  mDebugLoggingEnabled = Boolean.FALSE;
+    mBridgeConfig = getBridgeConfig(config);
+    mBridgeController = getBridgeController(mBridgeConfig);
+
+    // remember that init() has been called so can test in other methods.
+    mInitialized = true;
+
+  }
+  
+  public void doFacesRequest(ActionRequest request, ActionResponse response)
+    throws BridgeException,
+           BridgeDefaultViewNotSpecifiedException,
+           BridgeUninitializedException, 
+           NullPointerException
+  {
+    doFacesRequestPreamble(request, response, Bridge.PortletPhase.ACTION_PHASE);
     
-    // get bridgeEventHandler, processPublicRenderParameterHandler, preserveActionParams, excludedAttributes configuration settings.
-    mEventHandler = (BridgeEventHandler) portletContext.getAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + mPortletConfig.getPortletName() + 
-                                              "." + Bridge.BRIDGE_EVENT_HANDLER);
+    BridgeContext bCtx = getBridgeContext(request, response, Bridge.PortletPhase.ACTION_PHASE);
     
-    mProcessPRPHandler = (BridgePublicRenderParameterHandler) portletContext.getAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + mPortletConfig.getPortletName() + 
-                                              "." + Bridge.BRIDGE_PUBLIC_RENDER_PARAMETER_HANDLER);
-    mPreserveActionParams = 
-        (Boolean) portletContext.getAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + mPortletConfig.getPortletName() + 
-                                              "." + Bridge.PRESERVE_ACTION_PARAMS);
-    
-    mExcludedRequestAttributes = (List<String>) portletContext.getAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + mPortletConfig.getPortletName() +
-                                                      "." + Bridge.EXCLUDED_REQUEST_ATTRIBUTES);
-    if (mExcludedRequestAttributes != null)
-    {
-      // copy the list as we may be adding to it and don't want to worry that this might be immutable
-      mExcludedRequestAttributes = new ArrayList(mExcludedRequestAttributes);
-    }
-    else
+    try
     {
-      // Otherwise create an empty list
-      mExcludedRequestAttributes = new ArrayList(5);
+      mBridgeController.processPortletAction(bCtx);
     }
-    
-    // acquire any config information in faces-config.xml 
-    processFacesConfiguration(portletContext);
-    
-    
-    // Hack get the names of attrs to preserve from the FacesContext scope until render ends
-    String preserve = mPortletConfig.getInitParameter("org.apache.myfaces.portlet.faces.preserveFacesContextScopedAttrs");
-    if (preserve != null)
+    finally
     {
-      String[] attrs = preserve.split(",");
-      for (int i = 0; i < attrs.length; i++)
-      {
-        attrs[i] = attrs[i].trim();
-      }
-      mPreservedFacesContextScopeAttrs = Arrays.asList(attrs);
+      doFacesRequestPostScript(bCtx);
     }
+  }
+  
 
-    // Set up the synchronziation object for the RequestScopeMap as we don't
-    // want to sync on the PortletContext because its too broad. Note:
-    // needed
-    // because we not only need to sync the Map but also creating the Map
-    // and
-    // putting it in the PortletContext. Hence the sync object allows us
-    // to limit syncronizing the PortletContext to once per portlet (init
-    // time);
-
-    // TODO: What about synching on a static object or using a class lock?
-    //       Perhaps even the LRUMap itself if said map is a singleton?
-    synchronized (portletContext)
-    {
-      Object lock = portletContext.getAttribute(REQUEST_SCOPE_LOCK);
-      if (lock == null)
-      {
-        portletContext.setAttribute(REQUEST_SCOPE_LOCK, new Object());
-      }
-    }
+  public void doFacesRequest(EventRequest request, EventResponse response)
+    throws BridgeException,
+           BridgeDefaultViewNotSpecifiedException,
+           BridgeUninitializedException, 
+           NullPointerException
+  {
+    doFacesRequestPreamble(request, response, Bridge.PortletPhase.EVENT_PHASE);
     
-    // Wrapped desired Application with our own to override createComponent and
-    // insert our NamingContainerUIViewRoot component.  This was done through
-    // configuration via the META-INF/service/javax.faces.application.ApplicationFactory
-    
-    // Add self as ELContextListener to the Faces App so we can add the
-    // portletConfig to any newly created contexts.    
-    ((ApplicationFactory)FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY))
-        .getApplication().addELContextListener(this);
-
+    
+    BridgeContext bCtx = getBridgeContext(request, response, Bridge.PortletPhase.EVENT_PHASE);
 
-    // Process and cache the FacesServlet mappings for use by
-    // ExternalContext
-    WebConfigurationProcessor webConfig = new WebConfigurationProcessor(portletContext);
-    mFacesMappings = webConfig.getFacesMappings();
-    if (mFacesMappings == null || mFacesMappings.size() == 0)
+    try
     {
-      throw new BridgeException("BridgeImpl.init(): unable to determine Faces servlet web.xml mapping.");
+      mBridgeController.handlePortletEvent(bCtx);
     }
-
-    // Set defaults for each mode's last active view session attribute
-    mDefaultViewIdMap = (Map<String,String>) portletContext.getAttribute(
-                                Bridge.BRIDGE_PACKAGE_PREFIX + mPortletConfig.getPortletName()
-                                      + "." + Bridge.DEFAULT_VIEWID_MAP);
-
-    // remember that init() has been called so can test in other methods.
-    mInitialized = true;
-
-  }
-  
-  @Override
-  public void processEvent(SystemEvent event) throws AbortProcessingException
-  {
-    if(event instanceof PostConstructApplicationEvent)
+    finally
     {
-      // Install the Bridge StateManager -- wrapping the others -- we need to 
-      // be first (ratehr than last) so the action/render view save/restore will work
-      Application app = ((PostConstructApplicationEvent) event).getApplication();
-      app.setStateManager(new PortletStateManagerImpl(app.getStateManager()));
+      doFacesRequestPostScript(bCtx);
     }
   }
-  
-  
-  @Override
-  public boolean isListenerForSource(Object source)
-  {
-    //only for Application
-    return (source instanceof Application);
-  
-  }
-  
-  public void doFacesRequest(ActionRequest request, ActionResponse response)
+
+  public void doFacesRequest(RenderRequest request, RenderResponse response)
     throws BridgeException,
            BridgeDefaultViewNotSpecifiedException,
            BridgeUninitializedException, 
            NullPointerException
   {
-    if (!mInitialized)
-      throw new BridgeUninitializedException();
-    else if (request == null || response == null)
-      throw new NullPointerException("request or response parameter is null");
+    doFacesRequestPreamble(request, response, Bridge.PortletPhase.RENDER_PHASE); 
+
 
-    // First check to see whether this is a non-JSF request
-    if (request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER) != null)
+    BridgeContext bCtx = getBridgeContext(request, response, Bridge.PortletPhase.RENDER_PHASE);
+    try
     {
-      throw new BridgeNotAFacesRequestException("NonFaces target = "
-            + request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER));
+      mBridgeController.renderPortletBody(bCtx);
     }
-
-    // must wait until after init to get at the session
-    // since view mode mapping must always exist -- check it
-    StringBuffer keyBuf = new StringBuffer(30);
-    String key = keyBuf.append(Bridge.VIEWID_HISTORY).append(".view").toString();
-    if (request.getPortletSession().getAttribute(key) == null)
+    finally
     {
-      initViewHistoryDefaults(request.getPortletSession(), mDefaultViewIdMap);
+      doFacesRequestPostScript(bCtx);
     }
+  }
 
-    // Set the Portlet lifecycle phase as a request attribute so its
-    // available to Faces extensions -- allowing that code to NOT rely on
-    // instanceof which can fail if a portlet container uses a single class
-    // to implement both the action and render request/response objects
-    request.setAttribute(Bridge.PORTLET_LIFECYCLE_PHASE, Bridge.PortletPhase.ACTION_PHASE);
+
+  public void doFacesRequest(ResourceRequest request, ResourceResponse response)
+    throws BridgeException,
+           BridgeDefaultViewNotSpecifiedException,
+           BridgeUninitializedException, 
+           NullPointerException
+  {
+    doFacesRequestPreamble(request, response, Bridge.PortletPhase.RESOURCE_PHASE);
     
-    // set whether logging is enabled for other subsystems to see
-    request.setAttribute(BridgeImpl.LOGGING_ENABLED, mDebugLoggingEnabled);
+    BridgeContext bCtx = getBridgeContext(request, response, Bridge.PortletPhase.RESOURCE_PHASE);
     
-    // Set the PortletName for use throughout this request to read portlet specific context attrs
-    request.setAttribute(PORTLET_NAME_ATTRIBUTE, mPortletConfig.getPortletName());
-
-    // Set the FacesServletMapping attribute so the ExternalContext can
-    // pick it up and use it to reverse map viewIds to paths
-    if (mFacesMappings != null)
-    {
-      request.setAttribute(PortletExternalContextImpl.FACES_MAPPING_ATTRIBUTE, mFacesMappings);
-    }
-
-    // cache names of existing request attributes so can exclude them
-    // from being saved in the bridge's request scope. Note: this is done
-    // before
-    // acquiring the FacesContext because its possible (though unlikely)
-    // the application has inserted itself in this process and sets up
-    // needed request attributes.
-    List<String> preExistingAttributes = getRequestAttributes(request);
-
-    FacesContext context = null;
-    Lifecycle lifecycle = null;
-    String scopeId = null;
     try
     {
-      // Get the FacesContext instance for this request
-      lifecycle = getLifecycle();
-      context = getFacesContext(request, response, lifecycle, null);
-   
-      // in case a prior scope was managed temporarily on the session -- remove it
-      request.getPortletSession().removeAttribute(BRIDGE_PACKAGE_PREFIX + REQUEST_SCOPE_ID_RENDER_PARAM);
-      
-      // For actions we only execute the lifecycle phase
-
-      lifecycle.addPhaseListener(this);
-      
-      lifecycle.execute(context);
-
-      // If responseComplete don't save any state as we aren't falling through to render
-      // Usual occurs because of a redirect
-      if (!context.getResponseComplete())
-      {
-        // navigation didn't redirect
-        
-        // Finalize the action response -- key here is the reliance on
-        // ExternalContext.encodeActionURL to migrate info encoded
-        // in the actionURL constructed from the target of this
-        // navigation
-        // into the ActionResponse so it can be decoded in the
-        // asscociated portlet render.
-
-        finalizeActionResponse(context);
-        
-        // Process any Public Render parameter changes
-        processOutgoingPublicRenderParameters(context, request, response);
-        
-        
-        // Now check to see if we need to save the scope
-        // We don't save scope if the finalizeActionResponse detected 
-        // a mode change
-        Boolean noScope = (Boolean) request.getAttribute(PortletExternalContextImpl.NO_SCOPE);
-        if (noScope == null || noScope.equals(Boolean.FALSE))
-        {
-        
-          // Each action starts a new "action lifecycle"
-          // The Bridge preserves request scoped data and if so configured
-          // Action Parameters for the duration of an action lifecycle
-          scopeId = initBridgeRequestScope(request, response);
-
-          // Before preserving the request scope data in the bridge's
-          // request scope,
-          // put the Faces view into request scope. This is done because
-          // JSF 1.2 manages the tree save state opaquely exclusively in
-          // the render phase -- I.e. there is no JSF 1.2 way of having
-          // the
-          // bridge manually save and restore the view
-          saveFacesView(context);
-
-          // Spec requires we preserve the FACES_VIEW_STATE parameter
-          // in addition the portlet may be configured to preserve the
-          // rest of them.
-          saveActionParams(context);
-
-          // Because the portlet model doesn't execute its render phase
-          // within the same request scope but Faces does (assumes this),
-          // preserve the request scope data and the Faces view tree at
-          // RequestScope.
-          saveBridgeRequestScopeData(context, scopeId, preExistingAttributes, false);
-        }
+      // Determine whether this is a Faces resource or a regular one.
 
+      if (!isFacesResourceRequest(bCtx))
+      {
+        mBridgeController.renderNonFacesResource(bCtx);
       }
-
-    }
-    catch (Exception e)
-    {
-      if (mDebugLoggingEnabled.booleanValue()) 
-        mPortletConfig.getPortletContext().log("Exception thrown in doFacesRequest:action", e);
-      
-      if (!(e instanceof BridgeException))
+      else
       {
-        e =  new BridgeException(e);
+        mBridgeController.renderFacesResource(bCtx);
       }
-      throw (BridgeException) e;
+
     }
     finally
     {
-      dumpScopeId(scopeId, "ACTION_PHASE");
-      
-      if (lifecycle != null)
-      {
-        lifecycle.removePhaseListener(this);
-      }
-
-      if (context != null)
-      {
-        // remove the redirect attr so its not carried over to the 
-        // render in environments in which action/render are run in the
-        // same request ctx.  There are two potential attrs -- the one on 
-        // the request holds info if a redirect occurred within this request
-        // The one on the session caches the redirect that occurred during render 
-        // so it can be used in subsequent renders that occur before the action.
-        context.getExternalContext().getRequestMap().remove(BridgeImpl.REDIRECT_VIEWPARAMS);
-        context.getExternalContext().getSessionMap().remove(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS);
-        context.getExternalContext().getSessionMap().remove(BridgeImpl.RENDER_REDIRECT_PRPMAP);
-
-        context.release();
-      }
-      
-      // our servletrequestattributelistener uses this as an indicator of whether 
-      // its actively working on a request -- remove it to indicate we are done
-      request.removeAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
+      doFacesRequestPostScript(bCtx);
     }
   }
-
-  private void dumpScopeId(String scopeId, String phase)
+  
+  private boolean isFacesResourceRequest(BridgeContext bCtx)
   {
-    if (!mDebugLoggingEnabled.booleanValue()) return;
+    return (bCtx.getPortletRequest().getParameter(bCtx.getBridgeConfig().getViewIdRenderParameterName()) != null ||
+            bCtx.getPortletRequest().getParameter(Bridge.FACES_VIEW_ID_PARAMETER) != null ||
+            bCtx.getPortletRequest().getParameter(Bridge.FACES_VIEW_PATH_PARAMETER) != null);
+  }
 
-    // Get the data from the scope
-    PortletContext ctx = mPortletConfig.getPortletContext();
-    ctx.log("dumpScopeId: " + phase);
-    synchronized (ctx.getAttribute(REQUEST_SCOPE_LOCK))
-    {
-      // get the managedScopeMap
-      LRUMap requestScopeMap = (LRUMap) ctx.getAttribute(REQUEST_SCOPE_MAP);
-      // No scope for all renders before first action to this portletApp
-      if (requestScopeMap == null)
-      {
-        ctx.log("There are No saved scoped.  Can't match: " + scopeId);
-        return;
-      }
 
-      Map<String, Object> m = requestScopeMap.get(scopeId);
-      if (m == null)
-      {
-        ctx.log("Can't match scope: " + scopeId);
-        return;
-      }
+  public void destroy()
+  {
+    if (!mInitialized)
+      // do nothing if destroy an uninitialzed bridge
+      return;
 
-      Set<Map.Entry<String, Object>> set = m.entrySet();
-      Iterator<Map.Entry<String, Object>> i = set.iterator();
-      ctx.log("Elements in scope: " + scopeId);
-      while (i.hasNext())
-      {
-        Map.Entry<String, Object> entry = i.next();
-        ctx.log("     " + entry.getKey());
-      }
-      ctx.log("end dumpScopeId");
-    }
+    mInitialized = false;
+    
 
+    mBridgeController = null;
+    mBridgeConfig = null;
   }
   
-  private void dumpParameters(PortletRequest request)
+  
+  private BridgeConfig getBridgeConfig(PortletConfig config)
   {
-    if (!mDebugLoggingEnabled.booleanValue()) return;
+    // TODO: Use factory mechanism to get a BridgeConfig object
+    BridgeConfig bConfig = new BridgeConfigImpl();
+       
+    bConfig.setPortletConfig(config);
     
-    // Get the data from the scope
-    PortletContext ctx = mPortletConfig.getPortletContext();
-    ctx.log("dumpParameters: ");
-    Map<String, String[]> m = request.getParameterMap();
+    PortletContext portletContext = config.getPortletContext();
     
-    for (Map.Entry<String, String[]> e : m.entrySet())     
-    {
-      String key = e.getKey();
-      String[] values = e.getValue();
-      for (int i = 0; i < values.length; i++)
-      {
-        ctx.log("    key: " + key + "   value: " + values[i]);
-      }
-    }
+    // See if the bridge should log informational messages
+    Boolean enableLogging = (Boolean) portletContext.getAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + config.getPortletName() + 
+                                              "." + BridgeLogger.LOGGING_ENABLED_PORTLET_INIT_PARAM);
+    bConfig.getLogger().setEnabled((enableLogging != null) ? enableLogging : Boolean.FALSE);
     
-    ctx.log("dumpPublicParameters: ");
-    m = request.getPublicParameterMap();
     
-    for (Map.Entry<String, String[]> e : m.entrySet())     
-    {
-      String key = e.getKey();
-      String[] values = e.getValue();
-      for (int i = 0; i < values.length; i++)
-      {
-        ctx.log("    key: " + key + "   value: " + values[i]);
-      }
-    }
+    // get bridgeEventHandler, processPublicRenderParameterHandler, preserveActionParams, excludedAttributes configuration settings.
+    bConfig.setEventHandler((BridgeEventHandler) portletContext.getAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + config.getPortletName() + 
+                                              "." + Bridge.BRIDGE_EVENT_HANDLER));
     
-    ctx.log("dumpPrivateParameters: ");
-    m = request.getPrivateParameterMap();
+    bConfig.setPublicRenderParameterHandler((BridgePublicRenderParameterHandler) portletContext.getAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + config.getPortletName() + 
+                                              "." + Bridge.BRIDGE_PUBLIC_RENDER_PARAMETER_HANDLER));
+    bConfig.setPreserveActionParameters((Boolean) portletContext.getAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + config.getPortletName() + 
+                                              "." + Bridge.PRESERVE_ACTION_PARAMS));
+    
+    bConfig.setExcludedRequestAttributes((List<String>) portletContext.getAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + config.getPortletName() +
+                                                      "." + Bridge.EXCLUDED_REQUEST_ATTRIBUTES)); 
+    // acquire any config information in faces-config.xml 
+    processFacesConfiguration(bConfig);
+       
+    // Process and cache the FacesServlet mappings for use by
+    // ExternalContext
+    WebConfigurationProcessor webConfig = new WebConfigurationProcessor(portletContext);
+    bConfig.setFacesServletMappings(webConfig.getFacesMappings());
     
-    for (Map.Entry<String, String[]> e : m.entrySet())     
+    // Make sure we actually have mappings
+    List<String> facesMappings = bConfig.getFacesServletMappings();
+    if (facesMappings == null || facesMappings.isEmpty())
     {
-      String key = e.getKey();
-      String[] values = e.getValue();
-      for (int i = 0; i < values.length; i++)
-      {
-        ctx.log("    key: " + key + "   value: " + values[i]);
-      }
+      throw new BridgeException("BridgeImpl.init(): unable to determine Faces servlet web.xml mapping.");
     }
 
+    // Set defaults for each mode's last active view session attribute
+    bConfig.setDefaultViewMappings((Map<String,String>) portletContext.getAttribute(
+                                Bridge.BRIDGE_PACKAGE_PREFIX + config.getPortletName()
+                                      + "." + Bridge.DEFAULT_VIEWID_MAP));
+    return bConfig;
+  }
+  
+  private BridgeController getBridgeController(BridgeConfig bConfig)
+  {
+    // TODO -- use factory mechanism
+    BridgeController controller = new BridgeControllerImpl();
+    controller.init(bConfig);
+    return controller;
+  }
+  
+  private BridgeContext getBridgeContext(PortletRequest request, PortletResponse response, Bridge.PortletPhase phase)
+  {
+    // TODO:  Use factory mechanism to create
+    BridgeContext bCtx = new BridgeContextImpl();
+    
+    bCtx.setBridgeConfig(mBridgeConfig);
+    bCtx.setPortletContext(mBridgeConfig.getPortletConfig().getPortletContext());
+    bCtx.setPortletRequest(request);
+    bCtx.setPortletRequestPhase(phase);
+    bCtx.setPortletResponse(response);
+    bCtx.setPreFacesRequestAttrNames(Collections.list(request.getAttributeNames()));
+    
+    BridgeContext.setCurrentInstance(bCtx);
+    
+    sendExFacesSystemEvent(bCtx, BridgeInitializeRequestSystemEvent.class);
+    
+    return bCtx;
+
   }
   
-  public void doFacesRequest(EventRequest request, EventResponse response)
+  private void releaseBridgeContext(BridgeContext bCtx)
+  {
+    sendExFacesSystemEvent(bCtx, BridgeDestroyRequestSystemEvent.class);
+    bCtx.release();
+  }
+  
+  public void sendExFacesSystemEvent(BridgeContext bCtx, Class<? extends SystemEvent> eventClass)
+  {
+    FacesContext fCtx = new PreFacesFacesContext(bCtx.getBridgeConfig());
+  
+    // Send SystemEvent announcing the acquisition of the BridgeContext
+    fCtx.getApplication().publishEvent(fCtx, eventClass, bCtx);
+    
+    fCtx.release();
+  }
+  
+  public void doFacesRequestPreamble(PortletRequest request, PortletResponse response, Bridge.PortletPhase phase)
     throws BridgeException,
            BridgeDefaultViewNotSpecifiedException,
            BridgeUninitializedException, 
@@ -581,2446 +305,91 @@ public class BridgeImpl
     else if (request == null || response == null)
       throw new NullPointerException("request or response parameter is null");
     
-    // Do nothing if we don't have a BriegeEventHandler
-    if (mEventHandler == null)
-    {
-      // make sure the render parameters are carried forward into the next request
-      response.setRenderParameters(request);
-      // TODO: maybe log something here?
-      return;
-    }
-
-    // First check to see whether this is a non-JSF request
-    if (request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER) != null)
+    
+    if (phase == Bridge.PortletPhase.EVENT_PHASE)
     {
-      throw new BridgeNotAFacesRequestException("NonFaces target = "
-            + request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER));
+      // Make sure that at a minimum the current render parameters are carried forward
+      ((EventResponse)response).setRenderParameters((EventRequest)request);
+    
+      // Do nothing if we don't have a BriegeEventHandler
+      if (mBridgeConfig.getEventHandler() == null)
+      {
+        // TODO: maybe log something here?
+        return;
+      }
     }
 
-    // must wait until after init to get at the session
-    // since view mode mapping must always exist -- check it
-    StringBuffer keyBuf = new StringBuffer(30);
-    String key = keyBuf.append(Bridge.VIEWID_HISTORY).append(".view").toString();
-    if (request.getPortletSession().getAttribute(key) == null)
+    if (phase != Bridge.PortletPhase.RESOURCE_PHASE)
     {
-      initViewHistoryDefaults(request.getPortletSession(), mDefaultViewIdMap);
+      // First check to see whether this is a non-JSF request
+      if (request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER) != null)
+      {
+        throw new BridgeNotAFacesRequestException("NonFaces target = "
+              + request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER));
+      }
     }
 
     // Set the Portlet lifecycle phase as a request attribute so its
     // available to Faces extensions -- allowing that code to NOT rely on
     // instanceof which can fail if a portlet container uses a single class
     // to implement both the action and render request/response objects
-    request.setAttribute(Bridge.PORTLET_LIFECYCLE_PHASE, Bridge.PortletPhase.EVENT_PHASE);
-    
-    // set whether logging is enabled for other subsystems to see
-    request.setAttribute(BridgeImpl.LOGGING_ENABLED, mDebugLoggingEnabled);
+    request.setAttribute(Bridge.PORTLET_LIFECYCLE_PHASE, phase);
+  } 
+  
+  private void doFacesRequestPostScript(BridgeContext bCtx)
+  {
+    // Per spec remove the phase attribute.
+    bCtx.getPortletRequest().removeAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
     
-    // Set the PortletName for use throughout this request to read portlet specific context attrs
-    request.setAttribute(PORTLET_NAME_ATTRIBUTE, mPortletConfig.getPortletName());
-
-    // Set the FacesServletMapping attribute so the ExternalContext can
-    // pick it up and use it to reverse map viewIds to paths
-    if (mFacesMappings != null)
-    {
-      request.setAttribute(PortletExternalContextImpl.FACES_MAPPING_ATTRIBUTE, mFacesMappings);
-    }
-
-    // cache names of existing request attributes so can exclude them
-    // from being saved in the bridge's request scope. Note: this is done
-    // before
-    // acquiring the FacesContext because its possible (though unlikely)
-    // the application has inserted itself in this process and sets up
-    // needed request attributes.
-    List<String> preExistingAttributes = getRequestAttributes(request);
-    
-    // Make sure that at a minimum the current render parameters are carried forward
-    response.setRenderParameters(request);
-
-    FacesContext context = null;
-    Lifecycle lifecycle = null;
-    String scopeId = getRequestScopeId(request);
+    releaseBridgeContext(bCtx);
+  }
 
-    boolean restoredScope = false;
-    boolean removeScope = false;
+  private void processFacesConfiguration(BridgeConfig config)
+  {
+    PortletContext context = config.getPortletConfig().getPortletContext();
+    FacesConfigurationProcessor processor = new FacesConfigurationProcessor(context);
     
-    restoredScope = restoreBridgeRequestScopeData(request, scopeId);
+    // Get the public render parameter mappings
+    config.setPublicRenderParameterMappings(processor.getPublicParameterMappings());
     
-    try
+    // Get the write-behind response wrapper mappings
+    config.setWriteBehindRenderResponseWrapper(validateWrapperClass(processor.getWriteBehindRenderResponseWrapperClassName()));
+    config.setWriteBehindResourceResponseWrapper(validateWrapperClass(processor.getWriteBehindResourceResponseWrapperClassName()));
+    
+    // Update the excluded attributes list
+    List<String> list = processor.getExcludedAttributes();
+    List<String> existsingExcludes = config.getExcludedRequestAttributes();
+    
+    if (list != null)
     {
-      lifecycle = getLifecycle();
-      // Get the FacesContext instance for this request
-      context = getFacesContext(request, response, lifecycle, null);
-      
-      if (restoredScope)
-      {
-        // only restores if a render has never occurred in this scope
-        // once a render occurs, the view is saved/restored via Faces
-        restoreFacesView(context, scopeId);        
-      }
-   
-      // in case a prior scope was managed temporarily on the session -- remove it
-      // also ensure that the scopeId is now carried forward as a renderParameter
-      request.getPortletSession().removeAttribute(BRIDGE_PACKAGE_PREFIX + REQUEST_SCOPE_ID_RENDER_PARAM);
-      if (scopeId != null)
-      {
-        response.setRenderParameter(REQUEST_SCOPE_ID_RENDER_PARAM, scopeId);
-      }
-      
-      // add self as PhaseListener to prevent action phase from executing (after restoreView)
-      lifecycle.addPhaseListener(this);
-
-      // For actions we only execute the lifecycle phase
-      lifecycle.execute(context);
-      
-      // call the eventhandler to process
-      EventNavigationResult result = mEventHandler.handleEvent(context, request.getEvent());
-      
-      // If redirected either during lifecycle or event handling merely return as new target is already encoded in response. 
-      if (context.getResponseComplete()) 
-      {
-        // clear scopeid render parameter
-        removeScope = true;
-        return;
-      }
-      
-      if (result != null)
-      {
-        context.getApplication().getNavigationHandler().handleNavigation(context, result.getFromAction(), result.getOutcome());
-        // the navigation rule might indicate a redirect
-        if (context.getResponseComplete()) 
-        {
-          // clear scopeid render parameter
-          removeScope = true;
-          return;
-        }
-      }
-
-      finalizeActionResponse(context);
-        
-      // Process any Public Render parameter changes
-      processOutgoingPublicRenderParameters(context, request, response);
-        
-        
-      // Now check to see if we need to save the scope
-      // We don't save scope if the finalizeActionResponse detected 
-      // a mode change
-      Boolean noScope = (Boolean) request.getAttribute(PortletExternalContextImpl.NO_SCOPE);
-      if (noScope == null || noScope.equals(Boolean.FALSE))
+      ListIterator<String> i = list.listIterator();
+      while (i.hasNext())
       {
-        
-        // If event occurred before an action we don't have acope yet
-        if (scopeId == null)
+        String attr = i.next();
+        if (!existsingExcludes.contains(attr))
         {
-          scopeId = initBridgeRequestScope(request, response);
-          
-          // TBD: Mojarra 1.2_05 or later sets responseComplete if the restore occurs in
-          // a request that doesn't contain the isPostback marker (VIEW_STATE_PARAM).
-          // If we have no scopeId it means we received an event before the portlet
-          // was asked to render.  In these versions the following render call will
-          // fail to render because there is no VIEW_STATE_PARAM.  Should we artifucally
-          // set this here?
+          existsingExcludes.add(attr);
         }
-
-        // Before preserving the request scope data in the bridge's
-        // request scope,
-        // put the Faces view into request scope. This is done because
-        // JSF 1.2 manages the tree save state opaquely exclusively in
-        // the render phase -- I.e. there is no JSF 1.2 way of having
-        // the
-        // bridge manually save and restore the view
-        saveFacesView(context);
-
-        // Because the portlet model doesn't execute its render phase
-        // within the same request scope but Faces does (assumes this),
-        // preserve the request scope data and the Faces view tree at
-        // RequestScope.
-        saveBridgeRequestScopeData(context, scopeId, preExistingAttributes, false);
-      }
-      else
-      {
-        removeScope = true;
       }
-
+    } 
+  }  
+  
+  private Class<? extends BridgeWriteBehindResponse> validateWrapperClass(String className)
+  {
+    if (className == null)
+    {
+      return null;
     }
-    catch (Exception e)
+    
+    try
     {
-      if (!mDebugLoggingEnabled.booleanValue())
-        mPortletConfig.getPortletContext().log("Exception thrown in doFacesRequest:event", e);
-      
-      if (!(e instanceof BridgeException))
-      {
-        e = new BridgeException(e);
-      }
-      throw (BridgeException) e;
+      ClassLoader loader = Thread.currentThread().getContextClassLoader();
+      return (Class<? extends BridgeWriteBehindResponse>) loader.loadClass(className);
     }
-    finally
+    catch (Exception e)
     {
-      if (removeScope)
-      {
-        // Because we automatically copy forward all render parameters when the scope is not carried forward we must clear its param
-        removeRequestScopes(scopeId);
-      }
-      
-      dumpScopeId(scopeId, "EVENT_PHASE");
-      
-      if (lifecycle != null)
-      {
-        lifecycle.removePhaseListener(this);
-      }
-
-      if (context != null)
-      {
-        // remove the redirect attr so its not carried over to the 
-        // render in environments in which action/render are run in the
-        // same request ctx.  There are two potential attrs -- the one on 
-        // the request holds info if a redirect occurred within this request
-        // The one on the session caches the redirect that occurred during render 
-        // so it can be used in subsequent renders that occur before the action.
-        context.getExternalContext().getRequestMap().remove(BridgeImpl.REDIRECT_VIEWPARAMS);
-        context.getExternalContext().getSessionMap().remove(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS);
-        context.getExternalContext().getSessionMap().remove(BridgeImpl.RENDER_REDIRECT_PRPMAP);
-        context.release();
-      }
-      
-      // our servletrequestattributelistener uses this as an indicator of whether 
-      // its actively working on a request -- remove it to indicate we are done
-      request.removeAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
+      return null;
     }
-  }
+  } 
 
-
-  public void doFacesRequest(RenderRequest request, RenderResponse response)
-    throws BridgeException,
-           BridgeDefaultViewNotSpecifiedException,
-           BridgeUninitializedException, 
-           NullPointerException
-  {
-    if (!mInitialized)
-      throw new BridgeUninitializedException();
-    else if (request == null || response == null)
-      throw new NullPointerException("request or response parameter is null");
-
-    // First check to see whether this is a non-JSF render request
-    if (request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER) != null)
-    {
-      throw new BridgeNotAFacesRequestException("NonFaces target = "
-            + request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER));
-    }
-    
-    dumpParameters(request);
-    
-    // must wait until after init to get at the session
-    // since view mode mapping must always exist -- check it
-    StringBuffer keyBuf = new StringBuffer(30);
-    String key = keyBuf.append(Bridge.VIEWID_HISTORY).append(".view").toString();
-    if (request.getPortletSession().getAttribute(key) == null)
-    {
-      initViewHistoryDefaults(request.getPortletSession(), mDefaultViewIdMap);
-    }
-    
-    String scopeId = null;
-    boolean restoredScope = false;
-    boolean restoredView = false;
-
-    // Set the Portlet lifecycle phase as a request attribute so its
-    // available to Faces extensions -- allowing that code to NOT rely on
-    // instanceof which can fail if a portlet container uses a single class
-    // to implement both the action and render request/response objects
-    request.setAttribute(Bridge.PORTLET_LIFECYCLE_PHASE, Bridge.PortletPhase.RENDER_PHASE);
-    
-    // set whether logging is enabled for other subsystems to see
-    request.setAttribute(BridgeImpl.LOGGING_ENABLED, mDebugLoggingEnabled);
-
-    // Set the PortletName for use throughout this request to read portlet specific context attrs
-    request.setAttribute(PORTLET_NAME_ATTRIBUTE, mPortletConfig.getPortletName());
-    
-    // Set the WriteBehindResponse the ViewHandler should use
-    if (mWriteBehindRenderResponseWrapper != null)
-    {
-      request.setAttribute(BridgeImpl.WRITE_BEHIND_RESPONSE, mWriteBehindRenderResponseWrapper);
-    }
-    
-    // Set the FacesServletMapping attribute so the ExternalContext can
-    // pick it up and use it to reverse map viewIds to paths
-    if (mFacesMappings != null)
-    {
-      request.setAttribute(PortletExternalContextImpl.FACES_MAPPING_ATTRIBUTE, mFacesMappings);
-    }
-
-    // cache existing attributes in case a redirect occurs and
-    // we need to remove all but these preexisting ones.
-    List<String> preExistingAttributes = getRequestAttributes(request);
-    
-    // Now we need to determine if view we are going to render is the one
-    // encoded in the request (parameters) or specifically supplied
-    // either by the portlet itself or by a prior render redirect.
-    boolean clientDirectedView = ((request.getAttribute(Bridge.VIEW_ID) != null) ||
-        (request.getAttribute(Bridge.VIEW_PATH) != null));
-
-    // Now check to see if this is a Refresh (render) that follows a redirect
-    // If it is use the redirect information cached in the session as the basis
-    // for the request. 
-    QueryString redirectParams = (QueryString)
-              request.getPortletSession(true).getAttribute(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS);
-    
-    boolean modeChanged = hasModeChanged(request, redirectParams);
-
-    if (redirectParams != null)
-    {
-      if (clientDirectedView || modeChanged)  
-      {
-        // if we are too rely on the render redirect cache we must still
-        // be in the same mode and/or the portlet can't have set an explicit view to use
-        
-        // mode change/direct view set while in redirectDuringRender state
-        // clear this state (as we are no longer in it)
-        // and don't use the data
-        redirectParams = null;
-        request.getPortletSession().removeAttribute(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS);
-        request.getPortletSession().removeAttribute(BridgeImpl.RENDER_REDIRECT_PRPMAP);
-      }
-      else
-      {
-        // Incoming request may contain new PRP values -- if they do we need to update the RENDER_REDIRECT_VIEWPARAMS
-        updatePublicRedirectParams(request, redirectParams, (Map<String, String[]>)request.getPortletSession(true).getAttribute(BridgeImpl.RENDER_REDIRECT_PRPMAP));
-      }
-    }
-    
-    
-    // Get the scopeId -- will be null if first render
-    scopeId = getRequestScopeId(request);
-    
-    // First render request or a clientDirectedView
-    if (scopeId == null)
-    {
-      // first request 
-      // create a scope and store in the session until an action occurs
-      // pass null as we aren't a StateAwareResponse
-      scopeId = initBridgeRequestScope(request, null);
-    }
-    else if (clientDirectedView)
-    {
-      // Since the client has told us the specific view to use assume we shouldn't use existing scope
-      clearBridgeRequestScopeData(scopeId);
-    }
-    else
-    {
-      // If available -- restore the bridge request scope before getting the
-      // FacesContext in case anything in the context construction relies
-      // on these restored values.
-      // don't restore scope if mode changed
-      restoredScope = restoreBridgeRequestScopeData(request, scopeId);
-    } 
-
-    FacesContext context = null;
-    try
-    {
-      // Get the FacesContext instance for this request
-      Lifecycle lifecycle = getLifecycle();
-      context = getFacesContext(request, response, lifecycle, redirectParams);
-      ExternalContext extCtx = context.getExternalContext();
-
-      // Use request from ExternalContext in case its been wrapped by an
-      // extension
-      RenderRequest extRequest = (RenderRequest) extCtx.getRequest();
-
-      if (restoredScope)
-      {
-        // Because the Bridge is required to always save/restore the
-        // VIEW_STATE
-        // parameter -- always attempt a restore
-        extRequest = restoreActionParams(context);
-        
-        // only restores if first render after action
-        // afterwards not restored from Bridge request scope
-        // rather its saved/restored by Faces.
-        restoredView = restoreFacesView(context, scopeId);
-      }
-
-      // ensure that isPostback attribute set if VIEW_STATE param exists (though Faces generally
-      // uses the VIEW_STATE param as indication of whether its a postback or not -- this is a 
-      // bridge spec defined flag that can also be used.
-      if (extCtx.getRequestParameterValuesMap().containsKey(ResponseStateManager.VIEW_STATE_PARAM))
-      {
-        extCtx.getRequestMap().put(Bridge.IS_POSTBACK_ATTRIBUTE, Boolean.TRUE);
-      }
-      
-      doFacesRender(request, response, context, lifecycle, scopeId, preExistingAttributes);
-
-      // get contexts as they may have been reacquired if a redirect during render occurred.
-      context = FacesContext.getCurrentInstance();
-      extCtx = context.getExternalContext();
-    }
-    catch (Exception e)
-    {
-      // get context as it may have been reacquired if exception occurred during redirect during render.
-      context = FacesContext.getCurrentInstance();
-
-      if (!mDebugLoggingEnabled.booleanValue())
-        mPortletConfig.getPortletContext().log("Exception thrown in doFacesRequest:render", e);
-      
-      if (!(e instanceof BridgeException))
-      {
-        e = new BridgeException(e);
-      }
-      throw (BridgeException) e;
-    }
-    finally
-    {
-      dumpScopeId(scopeId, "RENDER_PHASE");
-
-      if (context != null)
-      {
-        context.release();
-      }
-      
-      // our servletrequestattributelistener uses this as an indicator of whether 
-      // its actively working on a request -- remove it to indicate we are done
-      request.removeAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
-    }
-  }
-
-
-  private boolean hasModeChanged(RenderRequest request, QueryString renderRedirectParams)
-  {
-    boolean hasModeChanged = false;
-    String targetViewId = null;
-    // if renderRedirectParams != null then this is a refresh following a render redirect
-    // In this case pull the scopeId from the redirectParams rather tahn the request
-    // as we will wrap the request (later) to expose these params to Faces
-    if (renderRedirectParams == null)
-    {
-      targetViewId =  request.getParameter(PortletExternalContextImpl.JSF_TARGET_VIEWID_RENDER_PARAMETER);
-    }
-    else
-    {
-      targetViewId = renderRedirectParams.getParameter(PortletExternalContextImpl.JSF_TARGET_VIEWID_RENDER_PARAMETER);
-    }
-    
-    if (targetViewId != null)
-    {
-      int i = targetViewId.indexOf(':');
-      if (i >= 0 )
-      {
-      
-        String mode = targetViewId.substring(0, i);
-        if (!mode.equalsIgnoreCase(request.getPortletMode().toString()))
-        {
-          hasModeChanged = true;
-        }
-      }
-    }
-    
-    return hasModeChanged;
-  }
-  
-  private void doFacesRender(
-      PortletRequest request,
-      MimeResponse response,
-      FacesContext context, 
-      Lifecycle lifecycle,
-      String scopeId, 
-      List<String> preExistingAttributes
-      )
-    throws BridgeException, BridgeUninitializedException, NullPointerException
-  {
-    // Note: if the scope wasn't restored then the Faces
-    // FACES_VIEW_STATE
-    // parameter will not have been carried into this render and hence
-    // default Faces impls will not see this render as occuring in a
-    // in a postback (isPostback() will return false. This means Faces
-    // will create a new Tree instead of restoring one -- the semantics
-    // one should get if the Bridge can't access its requestScope.
-      
-    try
-    {
-      // add self as PhaseListener to restore Messages and in the case of 
-      // the render phase, prevent excuting beyond restoreView
-      lifecycle.addPhaseListener(this);
-      
-      lifecycle.execute(context);
-    }
-    catch (Exception e)
-    {     
-      // now rethrow the exception as a BridgeException
-      if (!(e instanceof BridgeException))
-      {
-        e =  new BridgeException(e);
-      }
-      throw (BridgeException) e;
-    }
-    finally
-    {
-      lifecycle.removePhaseListener(this);
-    }
-
-    // check here to see if a redirect occurred -- if so rerun doFacesRequest
-    // for this new view
-    QueryString redirectParams = (QueryString) context.getExternalContext()
-            .getRequestMap().get(BridgeImpl.REDIRECT_VIEWPARAMS);
-    
-    if (redirectParams == null)
-    {
-      // In resource case and/or redirect overriden responseComplete 
-      // May have been set -- so don't ignore it
-      if (!context.getResponseComplete())
-      {
-        lifecycle.render(context);
-      }
-    }
-    else
-    {
-      redirectRender(context,
-        lifecycle, request, response, scopeId,
-        redirectParams, preExistingAttributes);
-      
-      context = FacesContext.getCurrentInstance();
-    }
-
-
-    // check here to see if a redirect occurred -- if so rerun doFacesRequest
-    // for this new view
-    // Can't use responseComplete because normal lifecycle.render completion
-    // sets this.
-    redirectParams = (QueryString) context.getExternalContext()
-            .getRequestMap().get(BridgeImpl.REDIRECT_VIEWPARAMS);
-    if ((redirectParams != null))
-    {
-      redirectRender(context,
-        lifecycle, request, response, scopeId,
-        redirectParams, preExistingAttributes);
-      context = FacesContext.getCurrentInstance();
-    }
-
-    if (scopeId == null) 
-    {
-      if (!mDebugLoggingEnabled.booleanValue())
-        context.getExternalContext().log("WARNING: Unexpected situation -- reached end of internal doFacesRender without a scopeId");
-      
-      // Don't expect to get here -- but just create a new scope
-      scopeId = createBridgeRequestScope(request);
-    }
-    
-    // At a minimum we need to update the VIEW_STATE_PARAM being maintained
-    // However, if this is a resource request then we also update the full scope
-    context.getExternalContext().getRequestMap().put(SCOPE_VIEW_KEY, getScopeViewKey(context.getExternalContext()));
-    saveFacesMessageState(context);
-    saveBridgeRequestScopeData(context, scopeId, preExistingAttributes, BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.RESOURCE_PHASE);
-    updateViewInfo(context, scopeId);
-  }
-
-  public void doFacesRequest(ResourceRequest request, ResourceResponse response)
-    throws BridgeException,
-           BridgeDefaultViewNotSpecifiedException,
-           BridgeUninitializedException, 
-           NullPointerException
-  {
-    if (!mInitialized)
-      throw new BridgeUninitializedException();
-    else if (request == null || response == null)
-      throw new NullPointerException("request or response parameter is null");
-
-    // Set the Portlet lifecycle phase as a request attribute so its
-    // available to Faces extensions -- allowing that code to NOT rely on
-    // instanceof which can fail if a portlet container uses a single class
-    // to implement both the action and render request/response objects
-    request.setAttribute(Bridge.PORTLET_LIFECYCLE_PHASE, Bridge.PortletPhase.RESOURCE_PHASE);
-    
-    // set whether logging is enabled for other subsystems to see
-    request.setAttribute(BridgeImpl.LOGGING_ENABLED, mDebugLoggingEnabled);
-
-    // Determine whether this is a Faces resource or a regular one.
-    if (!isFacesResourceRequest(request))
-    {
-      try
-      {
-        String target = request.getResourceID();
-        PortletRequestDispatcher rd = 
-          mPortletConfig.getPortletContext().getRequestDispatcher(target);
-        rd.forward(request, response);
-        return;
-      }
-      catch (Exception e)
-      {
-        if (!(e instanceof BridgeException))
-        {
-          e = new BridgeException(e);
-        }
-        throw (BridgeException) e;
-      }
-    }
-
-    // Otherwise this is a Faces resource
-    
-    // must wait until after init to get at the session
-    // since view mode mapping must always exist -- check it
-    StringBuffer keyBuf = new StringBuffer(30);
-    String key = keyBuf.append(Bridge.VIEWID_HISTORY).append(".view").toString();
-    if (request.getPortletSession().getAttribute(key) == null)
-    {
-      initViewHistoryDefaults(request.getPortletSession(), mDefaultViewIdMap);
-    }
-    
-
-    // Set the PortletName for use throughout this request to read portlet specific context attrs
-    request.setAttribute(PORTLET_NAME_ATTRIBUTE, mPortletConfig.getPortletName());
-    
-    // Set the WriteBehindResponse the ViewHandler should use
-    if (mWriteBehindResourceResponseWrapper != null)
-    {
-      request.setAttribute(BridgeImpl.WRITE_BEHIND_RESPONSE, mWriteBehindResourceResponseWrapper);
-    }
-
-
-    // Set the FacesServletMapping attribute so the ExternalContext can
-    // pick it up and use it to reverse map viewIds to paths
-    if (mFacesMappings != null)
-    {
-      request.setAttribute(PortletExternalContextImpl.FACES_MAPPING_ATTRIBUTE, mFacesMappings);
-    }
-
-    // cache names of existing request attributes so can exclude them
-    // from being saved in the bridge's request scope. Note: this is done
-    // before
-    // acquiring the FacesContext because its possible (though unlikely)
-    // the application has inserted itself in this process and sets up
-    // needed request attributes.
-    List<String> preExistingAttributes = getRequestAttributes(request);
-
-    FacesContext context = null;
-    String scopeId = null;
-    try
-    {
-      // Get the FacesContext instance for this request
-      Lifecycle lifecycle = getLifecycle();
-      context = getFacesContext(request, response, lifecycle, null);
-      ExternalContext extCtx = context.getExternalContext();
-
-      // Use request from ExternalContext in case its been wrapped by an
-      // extension
-      ResourceRequest extRequest = (ResourceRequest) extCtx.getRequest();
-      
-      // getting the scopeId is delayed until after getting the FacesContext
-      // because a resource request could be as a result of an embedded iFrame
-      // i.e. a child scope of the original render -- in this case don't use the render
-      // scope but the correct one contained within it
-      scopeId = getResourceRequestScopeId(extCtx, request);
-
-      doFacesRender(request, response, context, lifecycle, scopeId, preExistingAttributes);
-    }
-    catch (Exception e)
-    {
-      if (!mDebugLoggingEnabled.booleanValue())
-        context.getExternalContext().log("Exception thrown in doFacesRequest:resource", e);
-      
-      if (!(e instanceof BridgeException))
-      {
-        e = new BridgeException(e);
-      }
-      throw (BridgeException) e;
-    }
-    finally
-    {
-      dumpScopeId(scopeId, "RENDER_PHASE");
-
-      if (context != null)
-      {
-        context.release();
-      }
-      
-      // our servletrequestattributelistener uses this as an indicator of whether 
-      // its actively working on a request -- remove it to indicate we are done
-      request.removeAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
-    }
-  }
-  
-  private boolean isFacesResourceRequest(ResourceRequest request)
-  {
-    return (request.getParameter(PortletExternalContextImpl.JSF_TARGET_VIEWID_RENDER_PARAMETER) != null ||
-            request.getParameter(Bridge.FACES_VIEW_ID_PARAMETER) != null ||
-            request.getParameter(Bridge.FACES_VIEW_PATH_PARAMETER) != null);
-  }
-
-
-  public void destroy()
-  {
-    if (!mInitialized)
-      // do nothing if destroy an uninitialzed bridge
-      return;
-
-    mInitialized = false;
-    
-    // Remove the context listener
-    ((ApplicationFactory)FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY))
-        .getApplication().removeELContextListener(this);
-
-    // remove any scopes being managed for this portlet
-    // Each scope has a per portlet prefix -- pass in the prefix
-    // constructed by adding the prefix to an empty string.
-    removeRequestScopes(qualifyScopeId(mPortletConfig.getPortletName(), null, null, null));
-
-    mPortletConfig = null;
-  }
-  
-  /**
-   * ELContextListener impl
-   */
-  
-  public void contextCreated(ELContextEvent ece)
-  {
-    // Add the portletConfig to the ELContext so it is evaluated
-    ELContext elContext = ece.getELContext();
-
-    // FacesContext (where the Faces/Bridge ELContext is created doesn't have
-    // access to the PortletConfig which the Bridge ELResolver needs.
-    // The config object is added as an attribute here in the ContextListener.
-    // However only add to a EL context created within Faces as the JSP
-    // ELContext/Resolver will naturally resolve the config (as long as the
-    // page devleper has used the <portlet:defineObjects> tag.
-    // Because listeners are called at app scope we must ensure that only
-    // the active portlet's config is added to the ELContext.  To do this, check
-    // the portletName previously stored as a request attribute against the config.
-    
-    // Make sure our bridge instance is handling this context
-    String portletName = (String) ((FacesContext) elContext.getContext(FacesContext.class)).getExternalContext().getRequestMap().get(PORTLET_NAME_ATTRIBUTE);
-    if (portletName != null && portletName.equals(mPortletConfig.getPortletName()))
-    {
-      PortletELContextImpl portletELContext;
-      if (elContext instanceof PortletELContextImpl)
-      {
-        // Grr -- turns out that by the time my resolver is called the ELContext may
-        // have been wrapped -- so mark here as a FacesResolver and then do a put context
-        portletELContext = (PortletELContextImpl) elContext;
-        portletELContext.setFacesResolved(true);
-        // Put the portletConfig object into this Map
-        portletELContext.setPortletConfig(mPortletConfig);
-
-      }
-      else
-      {
-        // create a PortletELContext to hold future resolver state and place on this context
-        portletELContext = new PortletELContextImpl(elContext.getELResolver());
-        portletELContext.setFacesResolved(false);
-      }
-      elContext.putContext(PortletELContextImpl.class, portletELContext);
-    }
-  }
-
-  /*
-   * ServletRequestAttributeListener implementation
-   */
-  public void attributeAdded(ServletRequestAttributeEvent srae)
-  {
-    // use this phase attribute as an indicator of whether 
-    // we are actively working on a request
-    PortletPhase phase = (PortletPhase) srae.getServletRequest().getAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
-
-    // do nothing if before/after bridge processing or in the render phase.
-    // Don't care about render phase because we don't update/change the managed
-    // scope based on changes during render.
-    // ALSO: do nothing if not in the Bridge's managed request scope
-    if (phase == null || phase == PortletPhase.RENDER_PHASE || 
-        isExcludedFromBridgeRequestScope(srae.getName(),
-                                         srae.getValue(), 
-                                         (List<String>) srae.getServletRequest()
-                                            .getAttribute(PREEXISTING_ATTRIBUTE_NAMES)))
-    {
-      return;
-    }
-
-    // Otherwise -- see if the added attribute implements the bridge's 
-    // BridgeRequestScopeAdded annotation -- call each method so annotated
-    Object o = srae.getValue();
-    Method[] methods = o.getClass().getMethods();
-    for (int i = 0; i < methods.length; i++)
-    {
-      if (methods[i].isAnnotationPresent(BridgeRequestScopeAttributeAdded.class))
-      {
-        try
-        {
-          methods[i].invoke(o);
-        }
-        catch (Exception e)
-        {
-          // TODO: log problem
-          // do nothing and forge ahead
-          ;
-        }
-      }
-    }
-  }
-
-  public void attributeRemoved(ServletRequestAttributeEvent srae)
-  {
-    // use this phase attribute as an indicator of whether 
-    // we are actively working on a request
-    PortletPhase phase = (PortletPhase) srae.getServletRequest().getAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
-
-    // If not in a render this means the attribute has been removed before we have
-    // saved the request scope -- since the managed bean has been informed we are
-    // running in a portlet environment it should have ignored the PreDestroy.
-    // To make up for this we call its BridgePredestroy
-    if (phase != null && phase != PortletPhase.RENDER_PHASE)
-    {
-      notifyPreDestroy(srae.getValue()); // in outerclass (BridgeImpl)
-    }
-  }
-
-  public void attributeReplaced(ServletRequestAttributeEvent srae)
-  {
-    // use this phase attribute as an indicator of whether 
-    // we are actively working on a request
-    PortletPhase phase = (PortletPhase) srae.getServletRequest().getAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
-
-    // If in an action this means the attribute has been replaced before we have
-    // saved the action scope -- since the managed bean has been informed we are
-    // running in a portlet environment it should have ignored the PreDestroy.
-    // To make up for this we call its BridgePredestroy
-    if (phase != null && phase != PortletPhase.RENDER_PHASE)
-    {
-      notifyPreDestroy(srae.getValue()); // in outerclass (BridgeImpl)
-    }
-  }
-
-  private void initViewHistoryDefaults(PortletSession session, Map<String, String> viewIdDefaultMap)
-  {
-    Set<String> keys = viewIdDefaultMap.keySet();
-    Iterator<String> i = keys.iterator();
-    
-    while (i.hasNext())
-    {
-      String mode = i.next();
-      String modeView = viewIdDefaultMap.get(mode);
-      
-      if (modeView == null || modeView.length() == 0) continue;
-      
-      String defaultViewId = encodeMode(mode, modeView);
-      StringBuffer key = new StringBuffer(100);
-      session.setAttribute(
-          key.append(Bridge.VIEWID_HISTORY).append('.').append(mode).toString(),
-          defaultViewId);
-    }
-  }
-  
-  private String encodeMode(String mode, String viewId)
-  {
-    // if the viewId doesn't otherwise contain a mode param, encode it
-    // this is done so its already encoded in the viewid when developer uses
-    // to return to the mode/view
-    StringBuffer sb = new StringBuffer(viewId.length() + 30);
-    int queryStart = viewId.indexOf('?');
-    if (queryStart < 0)
-    {
-      return sb.append(viewId)
-        .append('?')
-        .append(Bridge.PORTLET_MODE_PARAMETER)
-        .append('=')
-        .append(mode)
-        .toString();
-    }
-    else
-    {
-      QueryString qs = new QueryString(viewId.substring(queryStart + 1), "UTF8");
-      qs.setParameter(Bridge.PORTLET_MODE_PARAMETER, mode);
-      return sb.append(viewId.substring(0, queryStart + 1)).append(qs.toString()).toString();
-    }
-  }
-  
-  @SuppressWarnings( "unchecked" )
-  private ArrayList<String> getPublicParameterNamesList()
-  {
-    Enumeration<String> e = mPortletConfig.getPublicRenderParameterNames();
-    ArrayList<String>  l = new ArrayList<String>();
-    if (!e.hasMoreElements()) return l;
-      
-    while (e.hasMoreElements())
-    {
-      l.add(e.nextElement());
-    }
-    // sort so we can use binary search to compare
-    Collections.sort(l);
-    return l;
-  }
-
-  private RenderRequest wrapRequestToRedirect(RenderRequest request,
-                              QueryString redirectParams)
-  {
-    // remove any bridge special marker params as these can't be set in a 
-    // render redirect
-    redirectParams.removeParameter(Bridge.DIRECT_LINK);
-    redirectParams.removeParameter(Bridge.PORTLET_MODE_PARAMETER);
-    redirectParams.removeParameter(Bridge.PORTLET_WINDOWSTATE_PARAMETER);
-    redirectParams.removeParameter(Bridge.PORTLET_SECURE_PARAMETER);
-
-    // Now turn the QueryString into a parameter map
-    Map<String, String[]> publicParamMap = new LinkedHashMap(redirectParams.numParameters());
-    Map<String, String[]> privateParamMap = new LinkedHashMap(redirectParams.numParameters());
-    ArrayList<String> publicParamNamesList = getPublicParameterNamesList();
-    Enumeration<String> nameEnum = redirectParams.getParameterNames();
-    while (nameEnum != null && nameEnum.hasMoreElements())
-    {
-      String name = nameEnum.nextElement();
-      Enumeration<String> valuesEnum = redirectParams.getParameterValues(name);
-      ArrayList<String> values = new ArrayList();
-      while (valuesEnum != null && valuesEnum.hasMoreElements())
-      {
-        values.add(valuesEnum.nextElement());
-      }
-      
-      if (Collections.binarySearch(publicParamNamesList, name) >= 0)
-      {
-        publicParamMap.put(name, values.toArray(new String[values.size()]));
-      }
-      else
-      {
-        privateParamMap.put(name, values.toArray(new String[values.size()]));
-      }
-    }
-
-    // now wrap the request object to expose only those params as are in QS
-    return (RenderRequest) new BridgeRenderRequestWrapper(request, privateParamMap, publicParamMap, false);
-  }
-  
-  private void updatePublicRedirectParams(PortletRequest request, QueryString redirectParams, Map<String, String[]> cachedPRPs)
-  {
-    Map<String, String[]> prps = request.getPublicParameterMap();
-    boolean modified = false;
-    
-    if (cachedPRPs == null)
-    {
-      cachedPRPs = Collections.EMPTY_MAP;
-    }
-    
-    // For each cachedPRP check to see if the prp exists in the current request and has the same value
-    // If any change -- remove/update in the QS
-    for (Map.Entry<String, String[]> entry : cachedPRPs.entrySet())
-    {
-      String key = entry.getKey();
-      if (prps.containsKey(key))
-      {
-        if (!Arrays.equals(prps.get(key), cachedPRPs.get(key)))
-        {
-          modified = true;
-          redirectParams.removeParameter(key);
-          for (String param : prps.get(key))
-          {
-            redirectParams.addParameter(key, param);
-          }
-        }
-      }
-      else
-      {
-        // Its in the cachedPRP but not the current request -- so its been cleared
-        modified = true;
-        redirectParams.removeParameter(key);
-      }
-    }
-    
-    // Now check the reverse -- add those that are in the current request but not the cache
-    for (Map.Entry<String, String[]> entry : prps.entrySet())
-    {
-      String key = entry.getKey();
-      if (!cachedPRPs.containsKey(key))
-      {
-        for (String param : prps.get(key))
-        {
-          modified = true;
-          redirectParams.addParameter(key, param);
-        }
-
-      }
-    }
-    
-    // Update the Map/redirectParams in the cache to the current values
-    if (modified)
-    {
-      request.getPortletSession().setAttribute(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS, redirectParams);
-      request.getPortletSession().setAttribute(BridgeImpl.RENDER_REDIRECT_PRPMAP, new HashMap<String, String[]>(prps));
-    }
-  }
-
-  private void redirectRender(FacesContext context,
-                              Lifecycle lifecycle,
-                              PortletRequest request,
-                              MimeResponse response,
-                              String scopeId,
-                              QueryString redirectParams,
-                              List<String> preExistingAttrs)
-  {
-    
-    if (context.getExternalContext().getSessionMap().get(BridgeImpl.RENDER_REDIRECT_PRPMAP) == null)
-    {
-      // Grab the current public parameter map so we can cache it so we can fix up render redisplays
-      // where the incoming request changes a PRP. Do it before redirect to make sure we don't
-      // perturb the result. This also ensures its done on the first redirect in this render -- which is what we want
-      // as this is the original PRPs of this request (unchanged by any other redirect)
-
-      context.getExternalContext().getSessionMap().put(BridgeImpl.RENDER_REDIRECT_PRPMAP,
-                                                       new HashMap<String, String[]>(request.getPublicParameterMap()));
-    }
-    
-    // The Bridge ViewHandler will set the HAS_RENDER_REDIRECTED_AFTER_FORWARD request attr if
-    // the redirect occurs after the dispatch.forward -- be sure to carry this forward 
-    // into the new wrapped request so the redirect will use include
-    Boolean hasRenderRedirectedAfterForward = (Boolean) request.getAttribute(HAS_RENDER_REDIRECTED_AFTER_FORWARD);
-    
-    // Reset the scope
-    if (scopeId != null)
-    {
-      clearBridgeRequestScopeData(scopeId);
-    }
-    
-    // close the FacesContext
-    context.release();
-    
-    
-    // Now put the HAS_RENDER_REDIRECTED_AFTER_FORWARDflag back
-    if (hasRenderRedirectedAfterForward != null)
-    {
-      request.setAttribute(HAS_RENDER_REDIRECTED_AFTER_FORWARD, hasRenderRedirectedAfterForward);
-    }
-    
-    // This removed the cache of preexisting request attributes -- so acquire again
-    getRequestAttributes(request);
-       
-    // start a new FacesContext
-    context = getFacesContext(request, response, lifecycle, redirectParams);
-    
-    // Deal with possible recursion by clearing the cache, then calling doFacesRender
-    // to render the redirect, and then finally setting the cache, if its hasn't
-    // already been set.  In the (recursive) multi-render redirect case, the 
-    // last redirect will be the only one that sets the cache.
-    context.getExternalContext().getSessionMap().remove(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS);
-    
-    // Run lifecycle.execute again ... then render
-    doFacesRender(request, response, context, lifecycle, scopeId, preExistingAttrs);
-    
-    // Reacquire the context as it may have changed if a recursive redirect render occurred
-    context = FacesContext.getCurrentInstance();
-    
-    // now cache the (last) redirect params on session for resuse in subsequent renders
-    // that occur before an action
-    if (context.getExternalContext().getSessionMap().get(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS) == null)
-    {
-      context.getExternalContext().getSessionMap().put(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS, redirectParams);
-    }
-
-  }
-
-  private FacesContextFactory getFacesContextFactory()
-    throws BridgeException
-  {
-    try
-    {
-      if (mFacesContextFactory == null)
-      {
-        mFacesContextFactory = 
-            (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
-      }
-      return mFacesContextFactory;
-    }
-    catch (FacesException e)
-    {
-      throw new BridgeException(e);
-    }
-  }
-  
-  private FacesContext getFacesContext(PortletRequest request, PortletResponse response, Lifecycle lifecycle, QueryString redirectParams)
-    throws FacesException
-  {
-    FacesContext context = null;
-    
-    context = 
-          getFacesContextFactory().getFacesContext(mPortletConfig.getPortletContext(), request, response, lifecycle);
-    
-    if (redirectParams != null)
-    {
-      // render redirect -- wrap the request
-      
-      // call ExternalContext.setRequest with wrapped request
-      context.getExternalContext().setRequest(wrapRequestToRedirect((RenderRequest)request, redirectParams));
-    }
-    
-    return context;
-
-  }
-
-  private Lifecycle getLifecycle()
-    throws BridgeException
-  {
-    try
-    {
-      if (mLifecycle == null)
-      {
-        LifecycleFactory lifecycleFactory = 
-          (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
-        String lifecycleId = 
-          mPortletConfig.getPortletContext().getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);
-        if (lifecycleId == null)
-        {
-          lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE;
-        }
-
-        mLifecycle = lifecycleFactory.getLifecycle(lifecycleId);
-      }
-      return mLifecycle;
-    }
-    catch (FacesException e)
-    {
-      throw new BridgeException(e);
-    }
-  }
-
-  private void saveFacesView(FacesContext context)
-  {
-
-    // first save any current Faces messages in the viewRoot
-    saveFacesMessageState(context);
-
-    // now place the viewRoot in the request scope
-    /*
-    UIViewRoot vr = context.getViewRoot();
-    Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
-    requestMap.put(FACES_VIEWROOT, vr);
-    
-    // Preserve the FC scope so its not lost when restart this lifecycle in the render
-    HashMap<Object, Object> preserved = preserveFacesContextScopeAttrs(context);
-    if (preserved != null)
-    {
-      requestMap.put(FACES_CONTEXT_SCOPE, preserved);
-    }
-    */
-    context.getExternalContext().getRequestMap().put(SAVED_VIEW_STATE, context.getApplication().getStateManager().saveView(context));
-    
-  }
-  
-  private HashMap<Object, Object> preserveFacesContextScopeAttrs(FacesContext context)
-  {
-     if (mPreservedFacesContextScopeAttrs == null || mPreservedFacesContextScopeAttrs.isEmpty())
-     {
-       return null;
-     }
-     
-     Map<Object, Object> attrs = context.getAttributes();
-     if (attrs == null || attrs.isEmpty())
-     {
-       return null;
-     }
-    
-    HashMap<Object, Object> m = new HashMap(5);
-
-     for (String key : mPreservedFacesContextScopeAttrs)
-     {
-       if (attrs.containsKey(key))
-       {
-         m.put(key, attrs.get(key));
-       }
-       else if (key.equalsIgnoreCase("org.apache.myfaces.portlet.faces.viewRoot"))
-       {
-         if (attrs.containsKey(context.getViewRoot()))
-         {
-           m.put(context.getViewRoot(), attrs.get(context.getViewRoot()));
-         }
-       }
-     }
-     return m;
-  }
-  
-  private boolean restoreFacesView(FacesContext context, String scopeId)
-  {
-    /*
-    Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
-    UIViewRoot viewRoot = (UIViewRoot) requestMap.remove(FACES_VIEWROOT);
-    if (viewRoot != null)
-    {
-      context.setViewRoot(viewRoot);
-    }
-    
-    
-    // restore FC scope without overwriting existing/new values
-    Map<Object, Object> attrs = (Map<Object, Object>) requestMap.remove(FACES_CONTEXT_SCOPE);
-    if (attrs != null)
-    {
-      Map<Object, Object> ctxAttrs = context.getAttributes();
-      for (Map.Entry<Object, Object> entry : attrs.entrySet())
-      {
-        if (!ctxAttrs.containsKey(entry.getKey()))
-        {
-          ctxAttrs.put(entry.getKey(), entry.getValue());
-        }
-      }
-    }
-    
-    // Delay removing from the bridge request scope until after we are sure that 
-    // render completes okay and the state is saved by Faces -- otherwise
-    // we won't be able to reply/retry,
-    
-    // Messages get restored in a phase listener
-    
-    return viewRoot != null;
-    */
-    return false;
-  }  
-
-  private void saveActionParams(FacesContext context)
-  {
-    // Always preserve the FACES_VIEW_STATE parameter as per spec.
-    // If portlet requests it, also preserve the rst of them.
-    ExternalContext ec = context.getExternalContext();
-    Map<String, Object> requestMap = ec.getRequestMap();
-    Map<String, String[]> requestParameterMap = ec.getRequestParameterValuesMap();
-    if (mPreserveActionParams.equals(Boolean.FALSE))
-    {
-      Map<String, String[]> m = new HashMap<String, String[]>(1);
-      if (requestParameterMap != null && 
-          requestParameterMap.containsKey(ResponseStateManager.VIEW_STATE_PARAM))
-      {
-        m.put(ResponseStateManager.VIEW_STATE_PARAM, 
-              requestParameterMap.get(ResponseStateManager.VIEW_STATE_PARAM));
-      } 
-      else
-      {
-        // Manufacture a dummy VIEW_STATE_PARAM so Faces will see the render as being in a Postback
-        // Issue this resolves is as follows:  Faces CommandLinks/Trinidad GoLinks are direct (href) links
-        // to JSF views.  They are encoded as action URLs but generally submitted as GETs (without VIEW_STATE param)
-        // When we fall through to the render following this action, the view is restored from cache (as usual)
-        // and then we call lifecycle.execute.  The Faces RI (Mojarra) unfortunately has code in its restoreView handler
-        // that if the UIViewRoot is already restored and isPostback is false (no VIEW_STATE param), then it sets 
-        // responseComplete.  By doing so the lifecycle.render is skipped and we get no markup output.
-        // By creating a dummy VIEW_STATE param we work around this -- and as this parameter is updated at the end of the
-        // render with the real one (because a save occurs) it shouldn't get out of sync with the cache view.
-        m.put(ResponseStateManager.VIEW_STATE_PARAM, 
-              new String[] {NULL_VIEW_STATE_PARAM_VALUE});
-      }
-      requestMap.put(REQUEST_PARAMETERS, m);
-    }
-    else
-    {
-      // place the parameter map in the portlet request scope
-      // so it will be promoted into the Bridge's request scope and hence
-      // be available during render.
-      Map<String, String[]> mutableParams = new HashMap<String, String[]>(requestParameterMap);
-      requestMap.put(REQUEST_PARAMETERS, mutableParams);
-    }
-  }
-
-  private void updateViewInfo(
-    FacesContext context,
-    String scopeId)
-  {
-    PortletContext portletContext = mPortletConfig.getPortletContext();
-
-    // Get the request scope lock -- because its added during init it should
-    // always be there.
-    synchronized (portletContext.getAttribute(REQUEST_SCOPE_LOCK))
-    {
-      // get the managedScopeMap
-      LRUMap requestScopeMap = (LRUMap) portletContext.getAttribute(REQUEST_SCOPE_MAP);
-
-      if (requestScopeMap == null)
-      {
-        // Have only done renders to this point -- so no scope to update
-        return;
-      }
-
-      // now see if this scope is in the Map
-      Map<String, Object> scopeMap = requestScopeMap.get(scopeId);
-      if (scopeMap == null)
-      {
-        // Scope has been previously removed -- so no scope to update
-        return;
-      }
-
-      // Now get the RequestParameters from the scope
-      @SuppressWarnings("unchecked")
-      Map<String, String[]> requestParams = (Map<String, String[]>) scopeMap.get(REQUEST_PARAMETERS);
-
-      if (requestParams == null)
-      {
-        requestParams = new HashMap<String, String[]>(1);
-        scopeMap.put(REQUEST_PARAMETERS, requestParams);
-      }
-
-      // Prepare the value for storing as a preserved parameter
-      // Store as an array of Strings with just one entry as per
-      // portlet request
-      String[] values = new String[1];
-      // First make sure we have a value to update
-      String updatedViewStateParam = 
-        (String) context.getExternalContext().getRequestMap().get(UPDATED_VIEW_STATE_PARAM);
-
-      if (updatedViewStateParam != null)
-      {
-        values[0] = updatedViewStateParam;
-
-        // finally update the value in the Map
-        requestParams.put(ResponseStateManager.VIEW_STATE_PARAM, values);
-      }
-        
-      // If this is the first render after an action the cached view will also
-      // be in the scope (as well as its FC scope.  Remove it so its not used again.
-      // get the managedScopeMap
-      scopeMap.remove(FACES_VIEWROOT);
-      scopeMap.remove(SAVED_VIEW_STATE);
-      Map<Object, Object> attrs = (Map<Object, Object>) scopeMap.remove(FACES_CONTEXT_SCOPE);
-      if (attrs != null)
-      {
-        attrs.clear();
-      }
-    }
-  }
-
-
-  private LRUMap createRequestScopeMap(PortletContext portletContext)
-  {
-    // see if portlet has defined how many requestScopes to manage
-    // for this portlet
-    int managedScopes = DEFAULT_MAX_MANAGED_REQUEST_SCOPES;
-
-    String managedScopesSetting = 
-      portletContext.getInitParameter(Bridge.MAX_MANAGED_REQUEST_SCOPES);
-    if (managedScopesSetting != null)
-    {
-      managedScopes = Integer.parseInt(managedScopesSetting);
-    }
-
-    return new LRUMap(managedScopes);
-  }
-
-  @SuppressWarnings("unchecked")
-  private RenderRequest restoreActionParams(FacesContext context)
-  {
-    // this is a little trickier then saving because there is no
-    // corresponding set. Instead we wrap the request object and set it
-    // on the externalContext.
-    ExternalContext ec = context.getExternalContext();
-    // Note: only available/restored if this scope was restored.
-    Map<String, String[]> m = (Map<String, String[]>) ec.getRequestMap().get(REQUEST_PARAMETERS);
-
-    // ensures current request returned if nothing to restore/wrap
-    RenderRequest wrapped = (RenderRequest) ec.getRequest();
-    if (m != null && !m.isEmpty())
-    {
-      wrapped = new BridgeRenderRequestWrapper(wrapped, m);
-      ec.setRequest(wrapped);
-    }
-    return wrapped;
-  }
-
-  public void saveFacesMessageState(FacesContext context)
-  {
-    // get the messages from Faces Context
-    Iterator<String> clientIds = context.getClientIdsWithMessages();
-    if (clientIds.hasNext())
-    {
-      FacesMessageState state = new FacesMessageState();
-      while (clientIds.hasNext())
-      {
-        String clientId = (String) clientIds.next();
-        for (Iterator<FacesMessage> messages = context.getMessages(clientId); messages.hasNext();)
-        {
-          state.addMessage(clientId, messages.next());
-        }
-      }
-      // save state in ViewRoot attributes
-      Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
-      requestMap.put(FACES_MESSAGES, state);
-    }
-  }
-
-  private void restoreFacesMessageState(FacesContext context)
-  {
-    // Only restore for Render request
-    if (context.getExternalContext().getRequest() instanceof RenderRequest)
-    {
-      Map<String, Object> map = context.getExternalContext().getRequestMap();
-
-      // restoring FacesMessages
-      FacesMessageState state = (FacesMessageState) map.get(FACES_MESSAGES);
-
-      if (state != null)
-      {
-        for (String clientId:state.getClientIds())
-        {
-          for (FacesMessage message:state.getMessages(clientId))
-          {
-            context.addMessage(clientId, message);
-          }
-        }
-      }
-    }
-  }
-  
-  private String getResourceRequestScopeId(ExternalContext extCtx, PortletRequest request)
-  {
-
-    // get the render scope this resource request is contained in
-    String scopeId = getRequestScopeId(request);
-       
-    if (scopeId == null)
-    {
-      // first request is a resource request
-      // create a scope and store in the session until an action occurs
-      // pass null as we aren't a StateAwareResponse
-      return initBridgeRequestScope(request, null);
-    }
-    
-    Map<String, Object> m = getScopeMap(scopeId);
-    
-    // If the scope is actually empty then this is first request -- hence 
-    // the resource must be targeting the same view
-    if (m == null || m.equals(Collections.EMPTY_MAP))
-    {
-      putBridgeRequestScopeData(scopeId, Collections.EMPTY_MAP, false);
-      return scopeId;
-    }
-    
-    // Check to see if this resource request is targeting the same view or a different one
-    Map<String, String> childResourceScopeMap = (Map<String, String>) m.get(CHILD_RESOURCE_REQUEST_SCOPE_MAP);
-    String scopeIdKey = (String) m.get(SCOPE_VIEW_KEY);
-    String childIdKey = getScopeViewKey(extCtx);

[... 1046 lines stripped ...]