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 2008/02/22 18:39:41 UTC
svn commit: r630260 - in /myfaces/portlet-bridge/core/trunk:
api/src/main/java/javax/portlet/faces/ api/src/main/resources/META-INF/
impl/src/main/java/org/apache/myfaces/portlet/faces/application/
impl/src/main/java/org/apache/myfaces/portlet/faces/br...
Author: mfreedman
Date: Fri Feb 22 09:39:34 2008
New Revision: 630260
URL: http://svn.apache.org/viewvc?rev=630260&view=rev
Log:
PORTLETBRIDGE-23 - Brings implementation up to date with the current draft. Changes include:
1) Supporting redirects during render
2) Call RestoreView phase listener when not using lifecyle to restore view in render.
3) defaultContentType/CharacterSetEncoding support.
4) removed adding APPLICATION_SCOPE map to session map.
Added:
myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeUninitializedException.java
myfaces/portlet-bridge/core/trunk/api/src/main/resources/META-INF/portlet1.0-bridge-faces1.2-faces-config-extensions.xsd
Modified:
myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/Bridge.java
myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/wrapper/BridgeRenderRequestWrapper.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletFacesContextImpl.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/el/PortletELResolver.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletSessionMap.java
Modified: myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/Bridge.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/Bridge.java?rev=630260&r1=630259&r2=630260&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/Bridge.java (original)
+++ myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/Bridge.java Fri Feb 22 09:39:34 2008
@@ -62,10 +62,6 @@
// Attribute signifying whether this render is a postback or not.
public static final String IS_POSTBACK_ATTRIBUTE = BRIDGE_PACKAGE_PREFIX + "isPostback";
- // Special session attribute name to hold the application_scope in the
- // portlet_scope of the session so these are accessible as well.
- public static final String APPLICATION_SCOPE_MAP = "javax.portlet.faces.ApplicationScopeMap";
-
// Names for special QueryString parameters names the Bridge recognizes in
// encodeActionURL as signifying to change the corresponding portlet values
// in the resulting URL
@@ -91,7 +87,16 @@
// Parameter that can be added to an ActionURL to signify it is a direct link
// and hence shouldn't be encoded by encodeActionURL as an actionURL
public static final String DIRECT_LINK = BRIDGE_PACKAGE_PREFIX + "DirectLink";
-
+
+ // Parameter that can be added to a ResourceURL or redirectURL to signify a back link to
+ // the current page should be added.
+ public static final String BACK_LINK = BRIDGE_PACKAGE_PREFIX + "BackLink";
+
+ // Parameter that can be added to a ResourceURL to signify that this URL
+ // should be encoded as an action and not a regular resource. This is used
+ // so h:outputLink can be used to represent a view navigation.
+ public static final String VIEW_LINK = BRIDGE_PACKAGE_PREFIX + "ViewLink";
+
// Session attribute pushed by bridge into session scope to give one access
// to Application scope
public static final String SESSION_APPLICATION_SCOPE_MAP = BRIDGE_PACKAGE_PREFIX
@@ -115,12 +120,12 @@
// calling the Bridge to process a request
public static final String DEFAULT_VIEWID = BRIDGE_PACKAGE_PREFIX
+ "defaultViewId";
-
+
// Following are the names of request attributes the Bridge must set before
// acquiring its first FacesContext/FacesContextFactory in each request
public static final String PORTLET_LIFECYCLE_PHASE = BRIDGE_PACKAGE_PREFIX + "phase";
- public static final String PORTLET_ISNAMESPACED_PROPERTY = "X-JAVAX-PORTLET-IS-NAMESPACED";
+ public static final String PORTLET_NAMESPACED_RESPONSE_PROPERTY = "X-JAVAX-PORTLET-NAMESPACED-RESPONSE";
// The possible JSR168 portlet lifecycle phazses
Added: myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeUninitializedException.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeUninitializedException.java?rev=630260&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeUninitializedException.java (added)
+++ myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeUninitializedException.java Fri Feb 22 09:39:34 2008
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
+ * law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
+ * for the specific language governing permissions and limitations under the License.
+ */
+package javax.portlet.faces;
+
+import javax.faces.FacesException;
+
+public class BridgeUninitializedException extends BridgeException
+{
+ //TODO: Update to use static serialVersionUID ala other exceptions
+ // when we figure out how to get maven to generate.
+
+ public BridgeUninitializedException()
+ {
+ super();
+ }
+
+ public BridgeUninitializedException(String message)
+ {
+ super(message);
+ }
+
+ public BridgeUninitializedException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public BridgeUninitializedException(Throwable cause)
+ {
+ super(cause);
+ }
+}
Modified: myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java?rev=630260&r1=630259&r2=630260&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java (original)
+++ myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java Fri Feb 22 09:39:34 2008
@@ -63,6 +63,11 @@
{
public static final String BRIDGE_CLASS = Bridge.BRIDGE_PACKAGE_PREFIX
+ "BridgeImplClass";
+ public static final String DEFAULT_CONTENT_TYPE = Bridge.BRIDGE_PACKAGE_PREFIX
+ + "defaultContentType";
+ public static final String DEFAULT_CHARACTERSET_ENCODING = Bridge.BRIDGE_PACKAGE_PREFIX
+ + "defaultCharacterSetEncoding";
+
public static final String BRIDGE_SERVICE_CLASSPATH = "META-INF/services/javax.portlet.faces.Bridge";
private Class<? extends Bridge> mFacesBridgeClass = null;
@@ -246,7 +251,7 @@
* Returns the className of the bridge implementation this portlet uses. Subclasses override to
* alter the default behavior. Default implementation first checks for a portlet context init
* parameter: javax.portlet.faces.BridgeImplClass. If it doesn't exist then it looks for the
- * resource file "/META-INF/services/javax.portlet.faces.Bridge" using the current threads
+ * resource file "META-INF/services/javax.portlet.faces.Bridge" using the current threads
* classloader and extracts the classname from the first line in that file.
*
* @return the class name of the Bridge class the GenericFacesPortlet uses. null if it can't be
@@ -263,6 +268,50 @@
}
return bridgeClassName;
}
+
+/**
+ * Returns the default content type for this portlet request. Subclasses override to
+ * alter the default behavior. Default implementation returns value of the portlet context init
+ * parameter: javax.portlet.faces.DefaultContentType. If it doesn't exist the portlet
+ * request's preferred response content type is returned.
+ *
+ * Note: This support is specific to the Portlet 1.0 Bridge. Its value is
+ * likely to be ignored by the Portlet 2.0 Bridge or later.
+ *
+ * @return the content type that should be used for this response.
+ */
+ public String getResponseContentType(PortletRequest request)
+ {
+ String contentType =
+ getPortletConfig().getPortletContext()
+ .getInitParameter(DEFAULT_CONTENT_TYPE);
+
+ if (contentType == null)
+ {
+ contentType = request.getResponseContentType();
+ }
+ return contentType;
+ }
+
+ /**
+ * Returns the character set encoding used for this portlet response. Subclasses override to
+ * alter the default behavior. Default implementation returns value of the portlet context init
+ * parameter: javax.portlet.faces.DefaultCharacterSetEncoding. If it doesn't exist null
+ * is returned.
+ *
+ * Note: This support is specific to the Portlet 1.0 Bridge. Its value is
+ * likely to be ignored by the Portlet 2.0 Bridge or later.
+ *
+ * @return the content type that should be used for this response.
+ */
+ public String getResponseCharacterSetEncoding(PortletRequest request)
+ {
+ return
+ getPortletConfig().getPortletContext()
+ .getInitParameter(DEFAULT_CHARACTERSET_ENCODING);
+ }
+
+
/**
* Returns the defaultViewId to be used for this request. The defaultViewId is depends on the
@@ -306,6 +355,13 @@
initBridge();
// Push information for Bridge into request attributes
setBridgeRequestContext(request, defaultViewId);
+
+ // Set the response ContentType/CharacterSet
+ setResponseContentType(
+ response,
+ getResponseContentType(request),
+ getResponseCharacterSetEncoding(request));
+
try
{
mFacesBridge.doFacesRequest(request, response);
@@ -355,10 +411,36 @@
}
}
- private void setBridgeRequestContext(PortletRequest request, String defaultViewId)
+ private void setBridgeRequestContext(
+ PortletRequest request,
+ String defaultViewId)
{
// Make the defaultViewId available to the Bridge
request.setAttribute(Bridge.DEFAULT_VIEWID, defaultViewId);
+
+ }
+
+ private void setResponseContentType(
+ RenderResponse response,
+ String contentType,
+ String charSetEncoding)
+ {
+ if (contentType == null)
+ {
+ return;
+
+ }
+ if (charSetEncoding != null)
+ {
+ StringBuffer buf = new StringBuffer(contentType);
+ buf.append(";");
+ buf.append(charSetEncoding);
+ response.setContentType(buf.toString());
+ }
+ else
+ {
+ response.setContentType(contentType);
+ }
}
private String getFromServicesPath(PortletContext context, String resourceName)
Added: myfaces/portlet-bridge/core/trunk/api/src/main/resources/META-INF/portlet1.0-bridge-faces1.2-faces-config-extensions.xsd
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/api/src/main/resources/META-INF/portlet1.0-bridge-faces1.2-faces-config-extensions.xsd?rev=630260&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk/api/src/main/resources/META-INF/portlet1.0-bridge-faces1.2-faces-config-extensions.xsd (added)
+++ myfaces/portlet-bridge/core/trunk/api/src/main/resources/META-INF/portlet1.0-bridge-faces1.2-faces-config-extensions.xsd Fri Feb 22 09:39:34 2008
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
+ targetNamespace="http://myfaces.apache.org/portletbridge" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:element name="excluded-attributes">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" name="excluded-attribute" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
\ No newline at end of file
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java?rev=630260&r1=630259&r2=630260&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java Fri Feb 22 09:39:34 2008
@@ -44,6 +44,9 @@
import javax.portlet.faces.annotation.PortletNamingContainer;
import javax.portlet.faces.component.PortletNamingContainerUIViewRoot;
+import org.apache.myfaces.portlet.faces.bridge.BridgeImpl;
+import org.apache.myfaces.portlet.faces.util.QueryString;
+
/**
* View handler implementation for JSF portlet bridge.
*
@@ -180,6 +183,16 @@
catch (IOException e)
{
throw new FacesException(e);
+ }
+
+ // If a redirect occurred -- merely return
+ // check here to see if a redirect occurred -- if so rerun doFacesRequest
+ // for this new view
+ QueryString redirectParams = (QueryString) context.getExternalContext()
+ .getRequestMap().get(BridgeImpl.BRIDGE_REDIRECT_VIEWPARAMS);
+ if ((redirectParams != null))
+ {
+ return;
}
// set up the ResponseWriter
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java?rev=630260&r1=630259&r2=630260&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java Fri Feb 22 09:39:34 2008
@@ -71,6 +71,7 @@
import javax.portlet.RenderResponse;
import javax.portlet.faces.Bridge;
import javax.portlet.faces.BridgeException;
+import javax.portlet.faces.BridgeUninitializedException;
import javax.portlet.faces.annotation.BridgePreDestroy;
import javax.portlet.faces.annotation.BridgeRequestScopeAttributeAdded;
import javax.portlet.faces.annotation.ExcludeFromManagedRequestScope;
@@ -87,6 +88,7 @@
import org.apache.myfaces.portlet.faces.bridge.wrapper.BridgeRenderRequestWrapper;
import org.apache.myfaces.portlet.faces.context.PortletExternalContextImpl;
+import org.apache.myfaces.portlet.faces.util.QueryString;
import org.apache.myfaces.portlet.faces.util.config.FacesConfigurationProcessor;
import org.apache.myfaces.portlet.faces.util.config.WebConfigurationProcessor;
@@ -97,6 +99,7 @@
// public so PortletStateManager can see/use
public static final String UPDATED_VIEW_STATE_PARAM = "org.apache.myfaces.portlet.faces.updatedViewStateParam";
+ public static final String BRIDGE_REDIRECT_VIEWPARAMS = "org.apache.myfaces.portlet.faces.redirectViewParams";
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";
@@ -115,6 +118,7 @@
private FacesContextFactory mFacesContextFactory = null;
private Lifecycle mLifecycle = null;
private List<String> mFacesMappings = null;
+ private boolean mInitialized = false;
public BridgeImpl()
@@ -126,6 +130,8 @@
throws BridgeException
{
//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();
@@ -185,15 +191,20 @@
{
throw new BridgeException("BridgeImpl.init(): unable to determine Faces servlet web.xml mapping.");
}
- for (int i = 0; i < mFacesMappings.size(); i++)
- {
- portletContext.log("Mapping: " + mFacesMappings.get(i));
- }
+
+ // remember that init() has been called so can test in other methods.
+ mInitialized = true;
+
}
public void doFacesRequest(ActionRequest request, ActionResponse response)
- throws BridgeException
+ throws BridgeException, 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
@@ -236,13 +247,14 @@
// For actions we only execute the lifecycle phase
getLifecycle().execute(context);
- // Check responseComplete -- if responseComplete the
- // lifecycle.execute
- // resulted in a redirect navigation. To preserve Faces semantics
- // the viewState isn't preserved nor is the data associated with the
- // action lifecycle.
-
- if (!context.getResponseComplete())
+ // Check if a redirect was called. If so encode the redirect viewId
+ // as the action response without saving state. Otherwise its not
+ // a redirect so save the state for the subsequent render.
+ QueryString redirectParams = (QueryString) context.getExternalContext().getRequestMap().get(BridgeImpl.BRIDGE_REDIRECT_VIEWPARAMS);
+
+ // Do nothing for redirect case because the ActionResponse is
+ // already encoded and no additional state needs to be saved.
+ if (redirectParams == null)
{
// navigation didn't redirect
@@ -265,7 +277,7 @@
// preserve the request scope data and the Faces view tree at
// RequestScope.
saveBridgeRequestScopeData(context, scopeId, preExistingAttributes);
-
+
// 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
@@ -274,8 +286,10 @@
// asscoicated portlet render.
finalizeActionResponse(context);
-
}
+
+
+
}
catch (Exception e)
{
@@ -340,10 +354,15 @@
}
public void doFacesRequest(RenderRequest request, RenderResponse response)
- throws BridgeException
+ throws BridgeException, BridgeUninitializedException, NullPointerException
{
- String scopeId = null;
+ if (!mInitialized)
+ throw new BridgeUninitializedException();
+ else if (request == null || response == null)
+ throw new NullPointerException("request or response parameter is null");
+ String scopeId = 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
@@ -356,6 +375,10 @@
{
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);
FacesContext context = null;
try
@@ -396,51 +419,8 @@
{
extCtx.getRequestMap().put(Bridge.IS_POSTBACK_ATTRIBUTE, Boolean.TRUE);
}
-
- // 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.
-
- // if the requestScope restored the ViewRoot then this must be
- // the first render after the action -- hence the tree isn't yet
- // stored/managed by Faces -- we can merely render it
- if (context.getViewRoot() == null)
- {
- // add self as PhaseListener to prevent action phases from
- // executing
- lifecycle.addPhaseListener(this);
- try
- {
- lifecycle.execute(context);
- }
- catch (Exception e)
- {
- // When exception occurs remove stored scope so don't
- // get stuck replaying the error when/if user refreshes
- if (scopeId != null)
- {
- removeRequestScopes(scopeId);
- }
- }
- finally
- {
- lifecycle.removePhaseListener(this);
- }
- }
- getLifecycle().render(context);
- // When we have navigated to this view between the action and render
- // the initial VIEW_STATE_PARAM reflects the actions view -- update
- // here to the one from this render so refresh will work.
- if (scopeId != null)
- {
- updateViewStateParam(context, scopeId);
- }
-
+ doFacesRender(request, response, context, lifecycle, scopeId, preExistingAttributes);
}
catch (Exception e)
{
@@ -474,14 +454,119 @@
}
}
}
+
+ private void doFacesRender(
+ RenderRequest request,
+ RenderResponse response,
+ FacesContext context,
+ Lifecycle lifecycle,
+ String scopeId,
+ List <String> preExistingAttributes
+ )
+ throws BridgeException, BridgeUninitializedException, NullPointerException
+ {
+ boolean redirectedDuringRender = false;
+
+ // 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.
+
+ // if the requestScope restored the ViewRoot then this must be
+ // the first render after the action -- hence the tree isn't yet
+ // stored/managed by Faces -- we can merely render it
+ if (context.getViewRoot() == null)
+ {
+ // add self as PhaseListener to prevent action phases from
+ // executing
+ lifecycle.addPhaseListener(this);
+ try
+ {
+ lifecycle.execute(context);
+ }
+ catch (Exception e)
+ {
+ // When exception occurs remove stored scope so don't
+ // get stuck replaying the error when/if user refreshes
+ if (scopeId != null)
+ {
+ removeRequestScopes(scopeId);
+ }
+ }
+ finally
+ {
+ lifecycle.removePhaseListener(this);
+ }
+ }
+ else
+ {
+ // using the cached view. Still call the preRestoreView phase listeners
+ // as some extensions depend on this being called per request.
+ PhaseListener[] listeners = lifecycle.getPhaseListeners();
+ PhaseEvent event = new PhaseEvent(context, PhaseId.RESTORE_VIEW, lifecycle);
+ for (PhaseListener listener:listeners)
+ {
+ if (listener.getPhaseId() == PhaseId.ANY_PHASE ||
+ listener.getPhaseId() == PhaseId.RESTORE_VIEW)
+ {
+ listener.beforePhase(event);
+ }
+ }
+ }
+
+ // check here to see if a redirect occurred -- if so rerun doFacesRequest
+ // for this new view
+ QueryString redirectParams = (QueryString) context.getExternalContext()
+ .getRequestMap().get(BridgeImpl.BRIDGE_REDIRECT_VIEWPARAMS);
+ if ((redirectParams == null))
+ {
+ getLifecycle().render(context);
+ }
+ else
+ {
+ redirectRender(context, lifecycle, request, response, redirectParams, preExistingAttributes);
+ context = FacesContext.getCurrentInstance();
+ redirectedDuringRender = true;
+ }
+
+
+ // check here to see if a redirect occurred -- if so rerun doFacesRequest
+ // for this new view
+ redirectParams = (QueryString) context.getExternalContext()
+ .getRequestMap().get(BridgeImpl.BRIDGE_REDIRECT_VIEWPARAMS);
+ if ((redirectParams != null))
+ {
+ redirectRender(context, lifecycle, request, response, redirectParams, preExistingAttributes);
+ context = FacesContext.getCurrentInstance();
+ redirectedDuringRender = true;
+ }
+
+ // When we have navigated to this view between the action and render
+ // the initial VIEW_STATE_PARAM reflects the actions view -- update
+ // here to the one from this render so refresh will work.
+ if (scopeId != null)
+ {
+ updateViewInfo(context, scopeId, redirectedDuringRender);
+ }
+ }
+
public void destroy()
{
+ if (!mInitialized)
+ // do nothing if destroy an uninitialzed bridge
+ return;
+
+ mInitialized = false;
+
// 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));
-
+
mPortletConfig = null;
}
@@ -575,7 +660,74 @@
notifyPreDestroy(srae.getValue()); // in outerclass (BridgeImpl)
}
}
+
+ private void redirectRender(FacesContext context,
+ Lifecycle lifecycle,
+ RenderRequest request,
+ RenderResponse response,
+ QueryString redirectParams,
+ List<String> preExistingAttrs)
+ {
+
+ // 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[]> paramMap = new LinkedHashMap(redirectParams.numParameters());
+ 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());
+
+ }
+ paramMap.put(name, values.toArray(new String[values.size()]));
+ }
+
+ // reset request attributes to those that existed before we were called.
+ Map<String, Object> m = context.getExternalContext().getRequestMap();
+ Set<Map.Entry<String, Object>> entrySet = m.entrySet();
+ Iterator<Map.Entry<String, Object>> i = entrySet.iterator();
+ String[] names = new String[400];
+ int count = 0;
+ while (i.hasNext())
+ {
+ Map.Entry<String, Object> entry = i.next();
+ if (!preExistingAttrs.contains(entry.getKey()))
+ {
+ // i.remove();
+ names[count++] = entry.getKey();
+ }
+ }
+
+ for (int j = 0; j < count; j++)
+ {
+ m.remove(names[j]);
+ }
+
+ // now wrap the request object to expose only those params as are in QS
+ BridgeRenderRequestWrapper requestWrapper = new BridgeRenderRequestWrapper(request, paramMap, false);
+ // close the FacesContext
+ context.release();
+ // start a new FacesContext
+ context =
+ getFacesContextFactory().getFacesContext(mPortletConfig, request, response, lifecycle);
+ // call ExternalContext.setRequest with wrapped request
+ context.getExternalContext().setRequest(requestWrapper);
+ // Run lifecycle.execute again ... then render
+ doFacesRender(request, response, context, lifecycle, null, preExistingAttrs);
+ return; // to continue on
+ }
+
private FacesContextFactory getFacesContextFactory()
throws BridgeException
{
@@ -676,17 +828,11 @@
}
}
- private void updateViewStateParam(FacesContext context, String scopeId)
+ private void updateViewInfo(
+ FacesContext context,
+ String scopeId,
+ boolean redirectedDuringRender)
{
-
- // First make sure we have a value to update
- String updatedViewStateParam = (String) context.getExternalContext()
- .getRequestMap().get(UPDATED_VIEW_STATE_PARAM);
-
- if (updatedViewStateParam == null)
- return;
-
- // Otherwise we need to update/store this value in the scope
PortletContext portletContext = mPortletConfig.getPortletContext();
// Get the request scope lock -- because its added during init it should
@@ -710,12 +856,6 @@
return;
}
- // 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];
- values[0] = updatedViewStateParam;
-
// Now get the RequestParameters from the scope
@SuppressWarnings("unchecked")
Map<String, String[]> requestParams = (Map<String, String[]>)scopeMap.get(REQUEST_PARAMETERS);
@@ -725,8 +865,36 @@
requestParams = new HashMap<String, String[]>(1);
scopeMap.put(REQUEST_PARAMETERS, requestParams);
}
- // finally update the value in the Map
- requestParams.put(ResponseStateManager.VIEW_STATE_PARAM, values);
+
+ // 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 (redirectedDuringRender)
+ {
+ // Add the VIEW_ID
+ values = new String[1];
+ values[0] = context.getViewRoot().getViewId();
+ // finally update the value in the Map
+ requestParams.put(PortletExternalContextImpl.REDIRECT_ID_PARAMETER_NAME, values);
+ }
+ else
+ {
+ // remove it in case was there from a prior redirect
+ requestParams.remove(PortletExternalContextImpl.REDIRECT_ID_PARAMETER_NAME);
+ }
}
}
@@ -908,7 +1076,8 @@
isInNamespace(s, "javax.faces.") ||
isInNamespace(s, "javax.servlet.") ||
isInNamespace(s, "javax.servlet.include.") ||
- s.equals(PREEXISTING_ATTRIBUTE_NAMES);
+ isInNamespace(s, "org.apache.myfaces.portlet.faces") ||
+ isInNamespace(s, "org.apache.myfaces.portlet.faces.context");
}
private boolean isConfiguredExcludedAttribute(String s)
@@ -1086,17 +1255,13 @@
// information
// in the subsequent render request(s).
+ String viewId = context.getViewRoot().getViewId();
+
+ // don't care about the return as it means nothing
ViewHandler viewHandler = context.getApplication().getViewHandler();
- String actionURL = viewHandler.getActionURL(context, context.getViewRoot().getViewId());
- String encodedActionURL = context.getExternalContext().encodeActionURL(actionURL);
+ String viewURL = viewHandler.getActionURL(context, viewId);
+ context.getExternalContext().encodeActionURL(viewURL);
- // Strictly speaking this is a redundant call (noop) as
- // ExternalContext.redirect() JSR 301 rules require redirects of
- // URLs containing viewIds (aka actionURLs) to be handled as
- // regular Faces navigation not full client redirects. Its
- // included here primarily to ensure that redirect is implemented
- // correctly.
- context.getExternalContext().redirect(encodedActionURL);
}
// notify this scope's attributes that they are being removed
@@ -1134,6 +1299,9 @@
private void removeRequestScopes(String scopePrefix)
{
+
+ if (scopePrefix == null)
+ return; // Nothing to do
// Get the RequestScope Map and remove all entries/scopes with this prefix
PortletContext portletContext = mPortletConfig.getPortletContext();
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/wrapper/BridgeRenderRequestWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/wrapper/BridgeRenderRequestWrapper.java?rev=630260&r1=630259&r2=630260&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/wrapper/BridgeRenderRequestWrapper.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/wrapper/BridgeRenderRequestWrapper.java Fri Feb 22 09:39:34 2008
@@ -30,14 +30,24 @@
{
private Map<String, String[]> mActionParams = null;
private Map<String, String[]> mCombinedParamMap = null;
+ private boolean mCombineParams = true;
public BridgeRenderRequestWrapper(RenderRequest request,
Map<String, String[]> actionParams)
throws IllegalArgumentException
{
+ this(request, actionParams, true);
+ }
+
+ public BridgeRenderRequestWrapper(RenderRequest request,
+ Map<String, String[]> actionParams,
+ boolean combineParams)
+ throws IllegalArgumentException
+ {
super(request);
mActionParams = actionParams;
+ mCombineParams = combineParams;
}
/**
@@ -148,13 +158,21 @@
@Override
public Map<String, String[]> getParameterMap()
{
- if (mActionParams == null || mActionParams.isEmpty())
+ if (!mCombineParams)
{
- return null;
+ return mActionParams;
}
-
- if (mCombinedParamMap == null)
+ else if (mActionParams == null || mActionParams.isEmpty())
{
+ return getParent().getParameterMap();
+ }
+ else if (mCombinedParamMap != null)
+ {
+ return mCombinedParamMap;
+ }
+ else
+ {
+ // Combine the two Maps
mCombinedParamMap = new LinkedHashMap<String, String[]>(getParent().getParameterMap());
// now walk through the actionParams adding those that aren't
@@ -170,8 +188,8 @@
// now make this an immutable Map
mCombinedParamMap = Collections.unmodifiableMap(mCombinedParamMap);
+
+ return mCombinedParamMap;
}
-
- return mCombinedParamMap;
}
}
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java?rev=630260&r1=630259&r2=630260&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java Fri Feb 22 09:39:34 2008
@@ -22,13 +22,17 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
+
import java.net.MalformedURLException;
import java.net.URL;
+
import java.security.Principal;
+
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.Locale;
import java.util.Map;
@@ -37,6 +41,8 @@
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletConfig;
@@ -54,6 +60,7 @@
import javax.portlet.faces.BridgeDefaultViewNotSpecifiedException;
import javax.portlet.faces.BridgeUtil;
+import org.apache.myfaces.portlet.faces.bridge.BridgeImpl;
import org.apache.myfaces.portlet.faces.util.QueryString;
import org.apache.myfaces.portlet.faces.util.URLUtils;
import org.apache.myfaces.portlet.faces.util.map.EnumerationIterator;
@@ -66,72 +73,71 @@
import org.apache.myfaces.portlet.faces.util.map.PortletRequestParameterMap;
import org.apache.myfaces.portlet.faces.util.map.PortletRequestParameterValuesMap;
import org.apache.myfaces.portlet.faces.util.map.PortletSessionMap;
+
/**
* This implementation of {@link ExternalContext} is specific to the portlet implementation.
*
* Methods of interests are: - encodeActionURL - redirect
*/
-public class PortletExternalContextImpl extends ExternalContext
+public class PortletExternalContextImpl
+ extends ExternalContext
{
- public static final String FACES_MAPPING_ATTRIBUTE = "org.apache.myfaces.portlet.faces.context.facesMapping";
-
- public static final String RENDER_POLICY_ATTRIBUTE = Bridge.BRIDGE_PACKAGE_PREFIX
- + "." + Bridge.RENDER_POLICY;
+ public static final String FACES_MAPPING_ATTRIBUTE =
+ "org.apache.myfaces.portlet.faces.context.facesMapping";
+ private static final String ENCODED_ACTION_URL_ATTRIBUTE_PREFIX =
+ "org.apache.myfaces.portlet.faces.context.";
- // Query parameter to store the original viewId in the query string
- public static final String VIEW_ID_QUERY_PARAMETER = "_VIEW_ID";
+ public static final String RENDER_POLICY_ATTRIBUTE =
+ Bridge.BRIDGE_PACKAGE_PREFIX + "." + Bridge.RENDER_POLICY;
// Render parameter to store the viewId
- public static final String ACTION_ID_PARAMETER_NAME = "_ACTION_ID";
+ public static final String ACTION_ID_PARAMETER_NAME = "_xACTION_ID";
+ public static final String REDIRECT_ID_PARAMETER_NAME = "org.apache.myfaces.portlet.faces.redirectViewParams";
+
- public static final String RESOURCE_METHOD_QUERY_PARAMETER = "_xResourceMethod";
- public static final String RESOURCE_URL_QUERY_PARAMETER = "_xResourceUrl";
- public static final String FACES_RESOURCE_QUERY_PARAMETER = "_xFacesResource";
- public static final String PROCESS_AS_RENDER_QUERY_PARAMETER = "_xProcessAsRender";
- public static final String REQUIRES_REWRITE_PARAMETER = "_xRequiresRewrite";
-
- private PortletContext mPortletContext;
- private PortletConfig mPortletConfig;
- private PortletRequest mPortletRequest;
- private PortletResponse mPortletResponse;
+ private PortletContext mPortletContext;
+ private PortletConfig mPortletConfig;
+ private PortletRequest mPortletRequest;
+ private PortletResponse mPortletResponse;
// Needed for distpach() which requires the actual PortletRequest/Response
// objects not wrapped one's (since wrapping isn't official in 168)
- private PortletRequest mOrigPortletRequest = null;
- private PortletResponse mOrigPortletResponse = null;
+ private PortletRequest mOrigPortletRequest = null;
+ private PortletResponse mOrigPortletResponse = null;
// External context maps
- private Map<String, Object> mApplicationMap = null;
- private Map<String, Object> mSessionMap = null;
- private Map<String, Object> mRequestMap = null;
- private Map<String, String> mRequestParameterMap = null;
- private Map<String, String[]> mRequestParameterValuesMap = null;
- private Map<String, String> mRequestHeaderMap = null;
- private Map<String, String[]> mRequestHeaderValuesMap = null;
- private Map<String, String> mInitParameterMap = null;
+ private Map<String, Object> mApplicationMap = null;
+ private Map<String, Object> mSessionMap = null;
+ private Map<String, Object> mRequestMap = null;
+ private Map<String, String> mRequestParameterMap = null;
+ private Map<String, String[]> mRequestParameterValuesMap = null;
+ private Map<String, String> mRequestHeaderMap = null;
+ private Map<String, String[]> mRequestHeaderValuesMap = null;
+ private Map<String, String> mInitParameterMap = null;
// maps for internal parameters (eg, those specified in query string of
// any defaultViewId)
- private Map<String, String> mInternalRequestParameterMap = Collections.emptyMap();
+ private Map<String, String> mInternalRequestParameterMap = Collections.emptyMap();
private Map<String, String[]> mInternalRequestParameterValuesMap = Collections.emptyMap();
- private PortletRequestHeaders mPortletRequestHeaders = null;
+ private PortletRequestHeaders mPortletRequestHeaders = null;
// Requested Faces view
- private String mViewId = null;
+ private String mViewId = null;
// Reverse engineered serlvet paths from mappings
- private List<String> mFacesMappings = null;
- private String mServletPath = null;
- private String mPathInfo = null;
+ private List<String> mFacesMappings = null;
+ private String mServletPath = null;
+ private String mPathInfo = null;
// Current Portlet phase
- private Bridge.PortletPhase mPhase = null;
+ private Bridge.PortletPhase mPhase = null;
@SuppressWarnings("unchecked")
- public PortletExternalContextImpl(PortletConfig portletConfig, PortletRequest portletRequest,
- PortletResponse portletResponse) throws FacesException
+ public PortletExternalContextImpl(PortletConfig portletConfig, PortletRequest portletRequest,
+ PortletResponse portletResponse)
+ throws FacesException
{
mPortletConfig = portletConfig;
mPortletContext = mPortletConfig.getPortletContext();
@@ -140,20 +146,9 @@
mPhase = (Bridge.PortletPhase) mPortletRequest.getAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
-
- // viewId is the actual context relative path to the resource
- mViewId = getViewId();
-
- // Now reverse engineer the servlet paths from the mappings
- // So Faces thinks was a client request
mFacesMappings = (List<String>) mPortletRequest.getAttribute(FACES_MAPPING_ATTRIBUTE);
- mapPathsFromViewId(mViewId, mFacesMappings);
-
-
- // JSF RI relies on a request attribute setting to properly handle
- // suffix mapping -- but because their suffix mapping code is servlet dependent
- // we need to set it for them
- setFacesMapping();
+
+ determineView();
}
@@ -229,8 +224,10 @@
else
{
path = url;
+ // construct an empty queryString to hold the viewId
+ queryStr = new QueryString("UTF8");
}
-
+
// Determine the viewId by inspecting the URL
if (!isRelativePath(path))
{
@@ -238,13 +235,16 @@
}
else
{
- viewId = getViewIdFromRelativePath(path);
+ viewId = getViewIdFromRelativePath(path);
}
if (viewId == null)
{
throw new FacesException("encodeActionURL: unable to recognize viewId");
}
+
+ // put the viewId in the QueryStr.
+ queryStr.addParameter(ACTION_ID_PARAMETER_NAME, viewId);
if (mPhase == Bridge.PortletPhase.RENDER_PHASE)
{ // render - write
@@ -254,142 +254,177 @@
// state)
RenderResponse renderResponse = (RenderResponse) getResponse();
PortletURL actionURL = renderResponse.createActionURL();
- actionURL.setParameter(ACTION_ID_PARAMETER_NAME, viewId);
-
- // Add extra parameters so they don't get lost
- if (queryStr != null)
+
+ // Add parameters so they don't get lost
+ Enumeration<String> list = queryStr.getParameterNames();
+ while (list.hasMoreElements())
{
- Enumeration<String> list = queryStr.getParameterNames();
- while (list.hasMoreElements())
+ String param = list.nextElement().toString();
+ if (param.equals(Bridge.PORTLET_MODE_PARAMETER))
{
- String param = list.nextElement().toString();
- if (param.equals(Bridge.PORTLET_MODE_PARAMETER))
+ try
{
- try
- {
- actionURL.setPortletMode(new PortletMode(queryStr.getParameter(param)));
- }
- catch (Exception e)
- {
- ; // do nothing -- just ignore
- }
+ actionURL.setPortletMode(new PortletMode(queryStr.getParameter(param)));
}
- else if (param.equals(Bridge.PORTLET_WINDOWSTATE_PARAMETER))
+ catch (Exception e)
{
- try
- {
- actionURL.setWindowState(new WindowState(queryStr.getParameter(param)));
- }
- catch (Exception e)
- {
- ; // do nothing -- just ignore
- }
+ ; // do nothing -- just ignore
}
- else if (param.equals(Bridge.PORTLET_SECURE_PARAMETER))
+ }
+ else if (param.equals(Bridge.PORTLET_WINDOWSTATE_PARAMETER))
+ {
+ try
+ {
+ actionURL.setWindowState(new WindowState(queryStr.getParameter(param)));
+ }
+ catch (Exception e)
+ {
+ ; // do nothing -- just ignore
+ }
+ }
+ else if (param.equals(Bridge.PORTLET_SECURE_PARAMETER))
+ {
+ try
{
- try
- {
- actionURL.setSecure(Boolean.getBoolean(queryStr.getParameter(param)));
- }
- catch (Exception e)
- {
- ; // do nothing -- just ignore
- }
+ actionURL.setSecure(Boolean.getBoolean(queryStr.getParameter(param)));
}
- else
+ catch (Exception e)
{
- actionURL.setParameter(param, queryStr.getParameter(param));
+ ; // do nothing -- just ignore
}
}
+ else
+ {
+ actionURL.setParameter(param, queryStr.getParameter(param));
+ }
}
// TODO hack to workaround double encoding problem
- String actionURLStr = actionURL.toString();
- actionURLStr = actionURLStr.replaceAll("\\&\\;", "&");
-
- return actionURLStr;
+ url = actionURL.toString();
+ url = url.replaceAll("\\&\\;", "&");
}
else
{ // action - write the viewId to navigational state
ActionResponse actionResponse = (ActionResponse) getResponse();
- actionResponse.setRenderParameter(ACTION_ID_PARAMETER_NAME, viewId);
-
- // set other request params (if any) into navigational states
- if (queryStr != null)
+ // set request params into navigational states
+ Enumeration<String> list = queryStr.getParameterNames();
+ while (list.hasMoreElements())
{
- Enumeration<String> list = queryStr.getParameterNames();
- while (list.hasMoreElements())
+ String param = list.nextElement();
+ if (param.equals(Bridge.PORTLET_MODE_PARAMETER))
{
- String param = list.nextElement();
- if (param.equals(Bridge.PORTLET_MODE_PARAMETER))
+ try
{
- try
- {
- actionResponse.setPortletMode(new PortletMode(queryStr.getParameter(param)));
- }
- catch (Exception e)
- {
- //TODO: Ignoring is probably dangerous here as it means that we are
- // EITHER using exceptions for flow control (which is extreemly
- // inefficient) or we should log a message saying what the issue
- // is. According to the Javadocs an exception is thrown here if the
- // portlet mode is not allowed or if sendRedirect has already been
- // called. In either case we should log an information type message
- // here.
- ; // do nothing -- just ignore
- }
+ actionResponse.setPortletMode(new PortletMode(queryStr.getParameter(param)));
}
- else if (param.equals(Bridge.PORTLET_WINDOWSTATE_PARAMETER))
+ catch (Exception e)
{
- try
- {
- actionResponse.setWindowState(new WindowState(queryStr.getParameter(param)));
- }
- catch (Exception e)
- {
- ; // do nothing -- just ignore
- }
+ //TODO: Ignoring is probably dangerous here as it means that we are
+ // EITHER using exceptions for flow control (which is extreemly
+ // inefficient) or we should log a message saying what the issue
+ // is. According to the Javadocs an exception is thrown here if the
+ // portlet mode is not allowed or if sendRedirect has already been
+ // called. In either case we should log an information type message
+ // here.
+ ; // do nothing -- just ignore
}
- else if (param.equals(Bridge.PORTLET_SECURE_PARAMETER))
+ }
+ else if (param.equals(Bridge.PORTLET_WINDOWSTATE_PARAMETER))
+ {
+ try
{
- ; // ignore -- do nothing as can't encode into an actionResponse
+ actionResponse.setWindowState(new WindowState(queryStr.getParameter(param)));
}
- else
+ catch (Exception e)
{
- actionResponse.setRenderParameter(param, queryStr.getParameter(param));
+ ; // do nothing -- just ignore
}
}
+ else if (param.equals(Bridge.PORTLET_SECURE_PARAMETER))
+ {
+ ; // ignore -- do nothing as can't encode into an actionResponse
+ }
+ else
+ {
+ actionResponse.setRenderParameter(param, queryStr.getParameter(param));
+ }
}
-
- return url;
}
+ // Because we want to support translating a redirect that occurs
+ // during a render as an in place navigation AND we can't reverse
+ // engineer the URL from the actionURL, we stash the queryStr on
+ // a request attribute, keyed with the generated URL. If this generated
+ // url is passed to redirect() we can get the queryStr back and
+ // process based on it. Do here rather then in the render if statement
+ // because redirect relies on this to handle non-encoded Faces URLs whether
+ // in an action or a render.
+ getRequestMap().put(ENCODED_ACTION_URL_ATTRIBUTE_PREFIX.concat(url), queryStr);
+
+ return url;
}
@Override
- public void redirect(String url) throws IOException
+ public void redirect(String url)
+ throws IOException
{
- // Distinguish between redirects within this app and external links
- // redirects within this app are dealt (elsewhere) as navigations
- // so do nothing. External links are redirected
-
- if (mPhase == Bridge.PortletPhase.ACTION_PHASE
- && (url.startsWith("#") || isExternalURL(url) || isDirectLink(url)))
+ // Distinguish between redirects to other Faces views in this app
+ // and everything else.
+ // Redirects to a view are dealt (elsewhere) as navigations --
+ // encode this information for later use by the bridge controller.
+ // Other links are redirected.
+
+ // First look to see if this is an already encoded
+ QueryString params = (QueryString) getRequestMap().get(ENCODED_ACTION_URL_ATTRIBUTE_PREFIX.concat(url));
+ if (params != null)
+ {
+ // Because we want to support translating a redirect that occurs
+ // during a render as an in place navigation AND we can't reverse
+ // engineer the URL from the actionURL, we stash the original URL on
+ // a request attribute, keyed with the generated URL. If this generated
+ // url is passed to redirect() we can get the original url back and
+ // process based on it.
+ getRequestMap().put(BridgeImpl.BRIDGE_REDIRECT_VIEWPARAMS, params);
+ }
+ else if ((url.startsWith("#") || isExternalURL(url) || isDirectLink(url)) ||
+ !isFacesURL(url))
{
- ((ActionResponse) getResponse()).sendRedirect(url);
+ if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
+ {
+ ((ActionResponse) getResponse()).sendRedirect(url);
+ FacesContext.getCurrentInstance().responseComplete();
+ }
+ } else
+ {
+ // is it an unencoded Faces URL -- process it.
+ // recurse on redirect after calling encodeActionURL which will
+ // cause the attribute to be set.
+ redirect(encodeActionURL(url));
+ FacesContext.getCurrentInstance().responseComplete();
}
-
- // TODO: Should we recognize a redirect during a rendere to an internal
- // link and treat as a navigation?
-
+
+ // else nothing to do
+ // TODO: is there an exception to throw here?
}
+
@Override
public String encodeResourceURL(String s)
{
+ boolean containsBackLinkMarker = false, containsViewLinkMarker = false;
+ if (s.indexOf(Bridge.BACK_LINK) != -1)
+ {
+ containsBackLinkMarker = true;
+ }
if (!isExternalURL(s))
{
+ // Only non-external URLs can be viewLinks
+ if (s.indexOf(Bridge.VIEW_LINK) != -1)
+ {
+ containsViewLinkMarker = true;
+ }
+
if (!s.startsWith("/"))
{
// must be a relative path -- convert it to contextPath relative
@@ -414,7 +449,7 @@
path = path.substring(0, path.lastIndexOf("/"));
s = URLUtils.convertFromRelative(path, s);
}
-
+
// prepend the context path since portletResponse.encodeURL() requires a full path URI
// Don't need to check return from getRequestContextPath because there must
// always be a vlaue even if an empty string
@@ -425,16 +460,30 @@
}
}
- String resourceURLStr = mPortletResponse.encodeURL(s);
+ // Check for backlink and viewlink markers -- if they exist replace
+ if (containsBackLinkMarker || containsViewLinkMarker)
+ {
+ s = replaceResourceQueryStringMarkers(s, containsBackLinkMarker, containsViewLinkMarker);
+ }
+
+ if (!containsViewLinkMarker)
+ {
+ s = mPortletResponse.encodeURL(s);
+ }
+ else
+ {
+ s = encodeActionURL(s);
+ }
// Avoid double encoding
- resourceURLStr = resourceURLStr.replaceAll("\\&\\;", "&");
+ s = s.replaceAll("\\&\\;", "&");
- return resourceURLStr;
+ return s;
}
@Override
- public void dispatch(String requestURI) throws IOException, FacesException
+ public void dispatch(String requestURI)
+ throws IOException, FacesException
{
if (requestURI == null)
{
@@ -450,9 +499,8 @@
if (prd == null)
{
- throw new IllegalArgumentException(
- "No request dispatcher can be created for the specified path: "
- + requestURI);
+ throw new IllegalArgumentException("No request dispatcher can be created for the specified path: " +
+ requestURI);
}
try
@@ -531,8 +579,9 @@
{
if (mRequestParameterMap == null)
{
- mRequestParameterMap = Collections.unmodifiableMap(new PortletRequestParameterMap( mPortletRequest,
- mInternalRequestParameterMap));
+ mRequestParameterMap =
+ Collections.unmodifiableMap(new PortletRequestParameterMap(mPortletRequest,
+ mInternalRequestParameterMap));
}
return mRequestParameterMap;
}
@@ -541,18 +590,17 @@
{
if (mRequestParameterValuesMap == null)
{
- mRequestParameterValuesMap = Collections
- .unmodifiableMap(new PortletRequestParameterValuesMap(
- mPortletRequest,
- mInternalRequestParameterValuesMap));
+ mRequestParameterValuesMap =
+ Collections.unmodifiableMap(new PortletRequestParameterValuesMap(mPortletRequest,
+ mInternalRequestParameterValuesMap));
}
return mRequestParameterValuesMap;
}
public Iterator<String> getRequestParameterNames()
{
- //Map is unmodifiable, so the iterator will be as well
- return getRequestParameterMap().keySet().iterator();
+ //Map is unmodifiable, so the iterator will be as well
+ return getRequestParameterMap().keySet().iterator();
}
public Map<String, String> getRequestHeaderMap()
@@ -626,7 +674,7 @@
}
@SuppressWarnings("unchecked")
- public Set<String> getResourcePaths(String s)
+ public Set<String> getResourcePaths(String s)
{
return mPortletContext.getResourcePaths(s);
}
@@ -694,12 +742,13 @@
@Override
public Iterator<Locale> getRequestLocales()
{
- //TODO: Cache this value...
+ //TODO: Cache this value...
return new EnumerationIterator<Locale>(mPortletRequest.getLocales());
}
@Override
- public URL getResource(String s) throws MalformedURLException
+ public URL getResource(String s)
+ throws MalformedURLException
{
return mPortletContext.getResource(s);
}
@@ -731,6 +780,11 @@
mRequestParameterValuesMap = null;
mRequestHeaderMap = null;
mRequestHeaderValuesMap = null;
+
+ // recalculate the view in case it has changed
+ // One case where it changes is when a redirect occurs
+ // during a render and we impl as a direct navigation
+ determineView();
}
/**
@@ -767,22 +821,22 @@
*
*/
@Override
- public void setRequestCharacterEncoding(String encoding) throws UnsupportedEncodingException,
- IllegalStateException
+ public void setRequestCharacterEncoding(String encoding)
+ throws UnsupportedEncodingException, IllegalStateException
{
/* TODO: Temporary workaround for JIRA PORTLETBRIDGE-14 until EG
* decides on best course of action.
- *
+ *
if (mPhase != Bridge.PortletPhase.ACTION_PHASE)
{
-
+
throw new IllegalStateException(
"PortletExternalContextImpl.setRequestCharacterEncoding(): Request must be an ActionRequest");
}
*/
-
- //Part of temp workaround. Do a noop if we are not in action phase
- if(mPhase == Bridge.PortletPhase.ACTION_PHASE)
+
+ //Part of temp workaround. Do a noop if we are not in action phase
+ if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
{
((ActionRequest) mPortletRequest).setCharacterEncoding(encoding);
}
@@ -894,8 +948,7 @@
{
if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
{
- throw new IllegalStateException(
- "PortletExternalContextImpl.getResponseCharacterEncoding(): Response must be a RenderRequest");
+ throw new IllegalStateException("PortletExternalContextImpl.getResponseCharacterEncoding(): Response must be a RenderRequest");
}
return ((RenderResponse) mPortletResponse).getCharacterEncoding();
@@ -930,8 +983,7 @@
{
if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
{
- throw new IllegalStateException(
- "PortletExternalContextImpl.getResponseContentType(): Response must be a RenderRequest");
+ throw new IllegalStateException("PortletExternalContextImpl.getResponseContentType(): Response must be a RenderRequest");
}
return ((RenderResponse) mPortletResponse).getContentType();
@@ -993,9 +1045,18 @@
/**
* Gets the view identifier we should use for this request.
*/
- private String getViewId() throws BridgeDefaultViewNotSpecifiedException
+ private String getViewId()
+ throws BridgeDefaultViewNotSpecifiedException
{
- String viewId = mPortletRequest.getParameter(ACTION_ID_PARAMETER_NAME);
+ // Use the REDIRECT_ID if it exists as this indicates a render redirect
+ // where we couldn't update the ACTION_ID
+ String viewId = mPortletRequest.getParameter(REDIRECT_ID_PARAMETER_NAME);
+
+ // Normal case is its returned in the render parameter
+ if (viewId == null)
+ {
+ viewId = mPortletRequest.getParameter(ACTION_ID_PARAMETER_NAME);
+ }
log("PortletExternalContextImpl.getViewId: found action_id = " + viewId);
@@ -1007,7 +1068,7 @@
{
throw new BridgeDefaultViewNotSpecifiedException();
}
-
+
log("PortletExternalContextImpl.getViewId: action_id not found, defaulting to: " + viewId);
}
@@ -1034,7 +1095,8 @@
{
String param = list.nextElement();
mInternalRequestParameterMap.put(param, queryStr.getParameter(param));
- mInternalRequestParameterValuesMap.put(param, new String[]{queryStr.getParameter(param)});
+ mInternalRequestParameterValuesMap.put(param, new String[]
+ { queryStr.getParameter(param) });
}
viewId = viewId.substring(0, queryStart);
@@ -1043,7 +1105,82 @@
return viewId;
}
-
+
+ private String replaceResourceQueryStringMarkers(String s, boolean hasBackLink,
+ boolean hasViewLink)
+ {
+ String path = null;
+ QueryString queryStr = null;
+ int queryStart = -1;
+
+ // First: split URL into path and query string
+ // Hold onto QueryString for later processing
+ queryStart = s.indexOf('?');
+
+ // references aren't in the querystring so nothing to do
+ if (queryStart == -1)
+ return s;
+
+ FacesContext context = FacesContext.getCurrentInstance();
+
+ queryStr = new QueryString(s.substring(queryStart + 1), "UTF8");
+ path = s.substring(0, queryStart);
+
+ Enumeration<String> list = queryStr.getParameterNames();
+ while (list.hasMoreElements())
+ {
+ String param = list.nextElement().toString();
+ if (hasBackLink && param.equals(Bridge.BACK_LINK))
+ {
+ try
+ {
+ // Set backlink as parameter using value as param name
+ queryStr.setParameter(queryStr.getParameter(param),
+ encodeActionURL(context.getApplication().getViewHandler().getActionURL(context,
+ context.getViewRoot().getViewId())));
+ ;
+ }
+ catch (Exception e)
+ {
+ ; // do nothing -- just ignore
+ }
+ // remove the backLink param.
+ queryStr.removeParameter(Bridge.BACK_LINK);
+ }
+ else if (hasViewLink && param.equals(Bridge.VIEW_LINK))
+ {
+ try
+ {
+ queryStr.removeParameter(Bridge.VIEW_LINK);
+ }
+ catch (Exception e)
+ {
+ ; // do nothing -- just ignore
+ }
+ }
+ }
+
+ // Now put the string back together
+ String qs = queryStr.toString();
+ if (qs.length() > 0)
+ {
+ s = path + "?" + qs;
+ }
+ else
+ {
+ s = path;
+ }
+
+ // Now transform the URL into an actionURL if this is a ViewLink
+ if (hasViewLink)
+ {
+ return encodeActionURL(s);
+ } else
+ {
+ return s;
+ }
+ }
+
private void mapPathsFromViewId(String viewId, List<String> mappings)
{
if (viewId == null || mappings == null)
@@ -1054,20 +1191,20 @@
mPathInfo = viewId;
return;
}
-
+
// The only thing that matters is we use a configured mapping
// So just use the first one
String mapping = mappings.get(0);
if (mapping.startsWith("*"))
{
// we are using suffix mapping
- viewId = viewId.substring(0, viewId.lastIndexOf('.'))
- + mapping.substring(mapping.indexOf('.'));
-
+ viewId =
+ viewId.substring(0, viewId.lastIndexOf('.')) + mapping.substring(mapping.indexOf('.'));
+
// we are extension mapped
mServletPath = viewId;
mPathInfo = null;
-
+
// Workaround Faces RI that has Servlet dependencies if this isn't set
mPortletRequest.setAttribute("javax.servlet.include.servlet_path", mServletPath);
}
@@ -1100,7 +1237,7 @@
{
viewId = viewId.substring(0, i);
}
-
+
int extLoc = viewId.lastIndexOf('.');
if (extLoc != -1 && extLoc > viewId.lastIndexOf('/'))
@@ -1136,11 +1273,8 @@
// Okay now figure out whether this is prefix or suffixed mapped
if (isSuffixedMapped(url, mFacesMappings))
{
- viewId = viewIdFromSuffixMapping(
- url,
- mFacesMappings,
- mPortletContext
- .getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME));
+ viewId =
+ viewIdFromSuffixMapping(url, mFacesMappings, mPortletContext.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME));
}
else if (isPrefixedMapped(url, mFacesMappings))
{
@@ -1207,6 +1341,28 @@
}
return false;
}
+
+ private void determineView()
+ {
+ // viewId is the actual context relative path to the resource
+ String viewId = getViewId();
+
+ if (mViewId != null && viewId.equals((mViewId)))
+ {
+ return; // No change
+ }
+
+ mViewId = viewId;
+
+ // Now reverse engineer the servlet paths from the mappings
+ // So Faces thinks was a client request
+ mapPathsFromViewId(mViewId, mFacesMappings);
+
+ // JSF RI relies on a request attribute setting to properly handle
+ // suffix mapping -- but because their suffix mapping code is servlet dependent
+ // we need to set it for them
+ setFacesMapping();
+ }
private String viewIdFromPrefixMapping(String url, List<String> mappings)
{
@@ -1234,22 +1390,22 @@
{
String mapping = null;
String servletPath = this.getRequestServletPath();
-
+
// if PathInfo == null we are suffixed mapped
if (this.getRequestPathInfo() == null)
{
mapping = servletPath.substring(servletPath.lastIndexOf('.'));
-
+
}
- else
+ else
{
mapping = servletPath;
}
-
+
this.getRequestMap().put("com.sun.faces.INVOCATION_PATH", mapping);
}
-
-
+
+
private boolean isAbsoluteURL(String url)
{
// Quick check for most common case
@@ -1269,12 +1425,18 @@
// i.e. contains no URI reserved characters
String scheme = url.substring(0, i);
- if (scheme.indexOf(";") != -1) return false;
- else if (scheme.indexOf("/") != -1) return false;
- else if (scheme.indexOf("#") != -1) return false;
- else if (scheme.indexOf("?") != -1) return false;
- else if (scheme.indexOf(" ") != -1) return false;
- else return true;
+ if (scheme.indexOf(";") != -1)
+ return false;
+ else if (scheme.indexOf("/") != -1)
+ return false;
+ else if (scheme.indexOf("#") != -1)
+ return false;
+ else if (scheme.indexOf("?") != -1)
+ return false;
+ else if (scheme.indexOf(" ") != -1)
+ return false;
+ else
+ return true;
}
private boolean isExternalURL(String url)
@@ -1299,6 +1461,23 @@
}
return true;
}
+
+ private boolean isFacesURL(String url)
+ {
+ String viewId = null;
+
+ // Determine the viewId by inspecting the URL
+ if (!isRelativePath(url))
+ {
+ viewId = getViewIdFromPath(url);
+ }
+ else
+ {
+ viewId = getViewIdFromRelativePath(url);
+ }
+
+ return viewId != null;
+ }
private boolean isDirectLink(String url)
{
@@ -1334,6 +1513,10 @@
{
url = url.substring(0, queryStart + 1) + query;
}
+ else
+ {
+ url = url.substring(0, queryStart);
+ }
}
}
@@ -1371,11 +1554,8 @@
// mapping
if (isSuffixedMapped(url, mFacesMappings))
{
- url = viewIdFromSuffixMapping(
- url,
- mFacesMappings,
- mPortletContext
- .getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME));
+ url =
+ viewIdFromSuffixMapping(url, mFacesMappings, mPortletContext.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME));
}
return url;
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletFacesContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletFacesContextImpl.java?rev=630260&r1=630259&r2=630260&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletFacesContextImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletFacesContextImpl.java Fri Feb 22 09:39:34 2008
@@ -281,7 +281,7 @@
try
{
PortletResponse pr = (PortletResponse) mExternalContext.getResponse();
- pr.addProperty(Bridge.PORTLET_ISNAMESPACED_PROPERTY, "true");
+ pr.addProperty(Bridge.PORTLET_NAMESPACED_RESPONSE_PROPERTY, "true");
}
catch (Exception e)
{
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/el/PortletELResolver.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/el/PortletELResolver.java?rev=630260&r1=630259&r2=630260&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/el/PortletELResolver.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/el/PortletELResolver.java Fri Feb 22 09:39:34 2008
@@ -36,9 +36,12 @@
import javax.faces.context.FacesContext;
import javax.portlet.PortletConfig;
import javax.portlet.PortletRequest;
+import javax.portlet.PortletSession;
import javax.portlet.faces.Bridge;
import javax.portlet.faces.BridgeUtil;
+import org.apache.myfaces.portlet.faces.util.map.PortletSessionMap;
+
public class PortletELResolver extends ELResolver
{
@@ -52,6 +55,8 @@
public static final int SESSION_PORTLET_SCOPE = 2;
public static final int PORTLET_PREFERENCE_VALUE = 3;
public static final int PORTLET_PREFERENCE_VALUES = 4;
+
+ private Map<String,Object> mAppScopeSessionMap = null;
public PortletELResolver()
{
@@ -94,7 +99,11 @@
return context.getContext(PortletConfig.class);
case SESSION_APPLICATION_SCOPE:
context.setPropertyResolved(true);
- return extCtx.getSessionMap().get(Bridge.APPLICATION_SCOPE_MAP);
+ if (mAppScopeSessionMap == null)
+ {
+ mAppScopeSessionMap = new PortletSessionMap(extCtx.getRequest(), PortletSession.APPLICATION_SCOPE);
+ }
+ return mAppScopeSessionMap;
case SESSION_PORTLET_SCOPE:
context.setPropertyResolved(true);
return extCtx.getSessionMap();
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java?rev=630260&r1=630259&r2=630260&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java Fri Feb 22 09:39:34 2008
@@ -158,6 +158,17 @@
initParameterMap();
return Collections.enumeration(mParameterNames);
}
+
+ public Map getParameterMap()
+ {
+ initParameterMap();
+ return mParameterMap;
+ }
+
+ public int numParameters()
+ {
+ return mParameterMap.size();
+ }
public String getParameter(String name)
{
@@ -166,17 +177,17 @@
return values == null ? null : values.get(0).getValue();
}
- public Enumeration<Object> getParameterValues(String name)
+ public Enumeration<String> getParameterValues(String name)
{
initParameterMap();
List<Parameter> params = mParameterMap.get(name);
if (params == null || params.isEmpty())
{
- List<Object> temp = Collections.emptyList();
+ List<String> temp = Collections.emptyList();
return Collections.enumeration(temp);
}
- List<Object> values = new ArrayList<Object>(params.size());
+ List<String> values = new ArrayList<String>(params.size());
for (Parameter param : params)
{
values.add(param.getValue());
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletSessionMap.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletSessionMap.java?rev=630260&r1=630259&r2=630260&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletSessionMap.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletSessionMap.java Fri Feb 22 09:39:34 2008
@@ -65,15 +65,15 @@
@Override
protected Object getAttribute(String key)
{
- PortletSession portletSession = mPortletRequest.getPortletSession(true);
-
- if (key.equals(Bridge.APPLICATION_SCOPE_MAP))
+ if (mPortletRequest != null)
{
- return getAppScopeMap(portletSession);
+ PortletSession portletSession = mPortletRequest.getPortletSession(true);
+
+ return portletSession.getAttribute(key, mScope);
}
else
{
- return portletSession.getAttribute(key, mScope);
+ throw new IllegalArgumentException(ILLEGAL_ARGUMENT);
}
}
@@ -123,25 +123,4 @@
throw new IllegalArgumentException(ILLEGAL_ARGUMENT);
}
}
-
- @SuppressWarnings("unchecked")
- private Map<String, Object> getAppScopeMap(PortletSession portletSession)
- {
- if (mScope != PortletSession.PORTLET_SCOPE)
- {
- return null;
- }
-
- Map<String, Object> m =
- (Map<String, Object>)portletSession.getAttribute(Bridge.APPLICATION_SCOPE_MAP);
-
- if (m == null)
- {
- m = new PortletSessionMap(mPortletRequest, PortletSession.APPLICATION_SCOPE);
- portletSession.setAttribute(Bridge.APPLICATION_SCOPE_MAP, m);
- }
-
- return m;
- }
-
}