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 ...]