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 2013/02/28 17:22:58 UTC
svn commit: r1451246 - in
/myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces:
bridge/ context/ util/map/
Author: mfreedman
Date: Thu Feb 28 16:22:58 2013
New Revision: 1451246
URL: http://svn.apache.org/r1451246
Log:
PORTLETBRIDGE-233: Add ability to create a dummy ExternalContext
PORTLETBRIDGE-232: Add ability for portlet to clear current request scope.
PORTLETBRIDGE-231: Request Threads can get stuck when Bridge removes a scope
PORTLETBRIDGE-221: Add explicit exclusions for trinidad in 329 branch
Modified:
myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestMap.java
myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java
myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java
Modified: myfaces/portlet-bridge/core/branches/trunk_2.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/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java?rev=1451246&r1=1451245&r2=1451246&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java (original)
+++ myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java Thu Feb 28 16:22:58 2013
@@ -43,6 +43,8 @@ import java.util.Set;
import java.util.Vector;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
import javax.el.ELContext;
import javax.el.ELContextEvent;
import javax.el.ELContextListener;
@@ -157,6 +159,10 @@ public class BridgeImpl
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";
+ private static final String REQUEST_SCOPE_REMOVAL_QUEUE = "org.apache.myfaces.portlet.faces.scopeRemovalQueue";
+ // Public to ADF bridge so they can clear the scope when the consumer's context has changed
+ public static final String CLEAR_REQUEST_SCOPE = "org.apache.myfaces.portlet.faces.clearRequestScope";
+
private static final int DEFAULT_MAX_MANAGED_REQUEST_SCOPES = 100;
private Boolean mPreserveActionParams = Boolean.FALSE;
@@ -240,6 +246,13 @@ public class BridgeImpl
if (lock == null)
{
portletContext.setAttribute(REQUEST_SCOPE_LOCK, new Object());
+
+ // create the queue (for all instances) to push/hold removed
+ // request scopes through to avoid this running/blocking on the scope lock
+ ConcurrentLinkedQueue<Map<String, Object>> queue = (ConcurrentLinkedQueue<Map<String, Object>>) new ConcurrentLinkedQueue();
+ portletContext.setAttribute(REQUEST_SCOPE_REMOVAL_QUEUE, queue);
+ Thread predestroyThread = new PreDestroyNotifierThread(queue);
+ predestroyThread.start();
}
}
@@ -336,6 +349,7 @@ public class BridgeImpl
context = getFacesContext(request, response, lifecycle, null);
// in case a prior scope was managed temporarily on the session -- remove it
+ removeRequestScopes(getRequestScopeId(request));
request.getPortletSession().removeAttribute(BRIDGE_PACKAGE_PREFIX + REQUEST_SCOPE_ID_RENDER_PARAM);
// For actions we only execute the lifecycle phase
@@ -1319,6 +1333,7 @@ public class BridgeImpl
// To make up for this we call its BridgePredestroy
if (phase != null && phase != PortletPhase.RENDER_PHASE)
{
+ // Call directly because outside of Scope lock
notifyPreDestroy(srae.getValue()); // in outerclass (BridgeImpl)
}
}
@@ -1335,6 +1350,7 @@ public class BridgeImpl
// To make up for this we call its BridgePredestroy
if (phase != null && phase != PortletPhase.RENDER_PHASE)
{
+ // Call directly because outside of Scope lock
notifyPreDestroy(srae.getValue()); // in outerclass (BridgeImpl)
}
}
@@ -1785,7 +1801,7 @@ public class BridgeImpl
managedScopes = Integer.parseInt(managedScopesSetting);
}
- return new LRUMap(managedScopes);
+ return new LRUMap(managedScopes, (ConcurrentLinkedQueue<Map<String, Object>>) portletContext.getAttribute(REQUEST_SCOPE_REMOVAL_QUEUE));
}
@SuppressWarnings("unchecked")
@@ -1942,17 +1958,27 @@ public class BridgeImpl
}
}
- // Only use this scope if it matches the current request mode
+
if (scopeId != null)
{
- // Its possible we didn't detect the mode change but its the wrong scope
- // as the scope is encoded with the mode -- confirm its right
- StringBuffer sb = new StringBuffer(10);
- String modeCheck = sb.append(":").append(request.getPortletMode().toString()).append(":").toString();
- if (scopeId.indexOf(modeCheck) < 0 )
+ // See if the Portlet has told us to clear this scope.
+ Boolean clearScope = (Boolean) request.getAttribute(CLEAR_REQUEST_SCOPE);
+ if (clearScope != null && clearScope.booleanValue())
+ {
+ clearBridgeRequestScopeData(scopeId);
+ }
+ else
+ // Only use this scope if it matches the current request mode
{
- // scope is for a different mode
- scopeId = null;
+ // Its possible we didn't detect the mode change but its the wrong scope
+ // as the scope is encoded with the mode -- confirm its right
+ StringBuffer sb = new StringBuffer(10);
+ String modeCheck = sb.append(":").append(request.getPortletMode().toString()).append(":").toString();
+ if (scopeId.indexOf(modeCheck) < 0 )
+ {
+ // scope is for a different mode
+ scopeId = null;
+ }
}
}
@@ -2003,6 +2029,7 @@ public class BridgeImpl
private void clearBridgeRequestScopeData(String scopeId)
{
+ // Call directly because outside of Scope lock
notifyPreDestroy(getScopeMap(scopeId));
putBridgeRequestScopeData(scopeId, Collections.EMPTY_MAP, false);
}
@@ -2777,11 +2804,13 @@ public class BridgeImpl
*/
private static final long serialVersionUID = 4372455368577337965L;
private int mMaxCapacity;
+ private ConcurrentLinkedQueue<Map<String, Object>> mQueue;
- public LRUMap(int maxCapacity)
+ public LRUMap(int maxCapacity, ConcurrentLinkedQueue<Map<String, Object>> notifyPreDestroyQueue)
{
super(maxCapacity, 1.0f, true);
mMaxCapacity = maxCapacity;
+ mQueue = notifyPreDestroyQueue;
}
@Override
@@ -2802,9 +2831,15 @@ public class BridgeImpl
dumpScopeId(key, "RemovePhase");
Map<String, Object> o = super.remove(key);
// notify attributes maintained in this object (map) they are going away
- // Method in the outer BridgeImpl class
- if (o != null)
- notifyPreDestroy(o);
+ // Done by pushing the Map to a queue that another thread is pulling from
+ if (o != null)
+ {
+ synchronized (mQueue)
+ {
+ mQueue.add(o);
+ mQueue.notifyAll();
+ }
+ }
return o;
}
@@ -2816,6 +2851,53 @@ public class BridgeImpl
}
}
+
+ private final class PreDestroyNotifierThread extends Thread
+ {
+ ConcurrentLinkedQueue <Map<String, Object>> mQueue;
+
+ public PreDestroyNotifierThread(ConcurrentLinkedQueue queue)
+ {
+ mQueue = queue;
+ }
+
+ public void run()
+ {
+ ArrayList<Map<String, Object>> scopes = (ArrayList<Map<String, Object>>) new ArrayList(10);
+ while (true)
+ {
+ synchronized(mQueue)
+ {
+ while (mQueue.isEmpty())
+ {
+ try
+ {
+ mQueue.wait();
+ }
+ catch (InterruptedException e)
+ {;}
+ }
+
+ for (Iterator<Map<String, Object>> i = mQueue.iterator(); i.hasNext();)
+ {
+ Map m = i.next();
+ if (m != Collections.EMPTY_MAP)
+ {
+ scopes.add((Map<String, Object>)m);
+ }
+ }
+ mQueue.clear();
+ }
+
+ for (Iterator<Map<String, Object>> i = scopes.iterator(); i.hasNext();)
+ {
+ Map<String, Object> m = i.next();
+ notifyPreDestroy(m);
+ }
+ scopes.clear();
+ }
+ }
+ }
// TODO: Should we store these as attributes of the ViewTree??? It would
// work as
Modified: myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java?rev=1451246&r1=1451245&r2=1451246&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java (original)
+++ myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java Thu Feb 28 16:22:58 2013
@@ -279,7 +279,10 @@ public class PortletExternalContextImpl
boolean isPortletURLSelfReference = false;
boolean isStrictXhtmlEncoded = isStrictXhtmlEncoded(url);
Bridge.PortletPhase urlType = Bridge.PortletPhase.ACTION_PHASE;
-
+
+ // We support creating a dummy ExternalContext prior to activating Faces. However this op doesn't make sense
+ assert FacesContext.getCurrentInstance() != null;
+
// First check to see if the special URI indicating we should encode
// a Nonfaces target to just the current portlet (without an associated
// path based resource).
@@ -566,6 +569,10 @@ public class PortletExternalContextImpl
public void redirect(String url)
throws IOException
{
+
+ // We support creating a dummy ExternalContext (before FacesContext established) but some ops aren't available
+ assert FacesContext.getCurrentInstance() != null;
+
Bridge.PortletPhase phase = getPortletPhase();
switch (phase)
@@ -725,6 +732,7 @@ public class PortletExternalContextImpl
{
if (isPortletURL(s))
{
+ // Fails assert in dummy externalContext situation
return urlEncode(encodeResourceAsViewNavigationURL(s));
}
else if (isOpaqueURL(s))
@@ -738,6 +746,7 @@ public class PortletExternalContextImpl
}
else if (isViewLink(s))
{
+ // Fails assert in dummy externalContext situation
return urlEncode(encodeResourceAsViewNavigationURL(s));
}
else if (!isInProtocolResourceLink(s))
@@ -947,6 +956,9 @@ public class PortletExternalContextImpl
public void dispatch(String requestURI)
throws IOException, FacesException
{
+ // We support creating a dummy ExternalContext (before FacesContext established) but some ops aren't available
+ assert FacesContext.getCurrentInstance() != null;
+
if (requestURI == null)
{
throw new java.lang.NullPointerException();
@@ -1187,6 +1199,9 @@ public class PortletExternalContextImpl
public String encodeNamespace(String s)
{
+ // We support creating a dummy ExternalContext (before FacesContext established) but some ops aren't available
+ assert FacesContext.getCurrentInstance() != null;
+
// Supposedly if this attribute is present we are running in Liferay
if (getRequestMap().get("THEME_DISPLAY") == null)
{
@@ -1823,6 +1838,8 @@ public class PortletExternalContextImpl
String backLinkValue = queryStr.removeParameter(Bridge.BACK_LINK);
if (backLinkValue!= null)
{
+ // We support creating a dummy ExternalContext (before FacesContext established) but some ops aren't available
+ assert context != null;
queryStr.setParameter(backLinkValue, encodeActionURL(context.getApplication().getViewHandler().getActionURL(context,
context.getViewRoot().getViewId())), false);
}
@@ -2225,7 +2242,7 @@ public class PortletExternalContextImpl
int i = url.indexOf(ctxPath);
int q = url.indexOf('?');
- if (i != -1 && i < q)
+ if (i != -1 && (q == -1 || i < q))
{
// make sure its actually the ContextPath and not the beginning of the target.
// I.e. avoid thinking /simple.jspx contains the context path when the CP is
Modified: myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestMap.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestMap.java?rev=1451246&r1=1451245&r2=1451246&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestMap.java (original)
+++ myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestMap.java Thu Feb 28 16:22:58 2013
@@ -48,6 +48,8 @@ public class PortletRequestMap extends P
{
if (mPortletRequest != null)
{
+ Object attr = mPortletRequest.getAttribute(key);
+
// Total Hack -- The bridge has to delay computing the viewId (and
// hence the paths until the paths are asked for so as not to prematurely
// read the request parameters thus avoiding exceptions from
@@ -56,8 +58,10 @@ public class PortletRequestMap extends P
// because it doesn't read the paths from the EC -- setting the paths
// has the side effect of setting the RI request attribute (another hack)
// which the RI uses instead of calculating.
- Object attr = mPortletRequest.getAttribute(key);
- if (attr == null && key.equals("com.sun.faces.INVOCATION_PATH"))
+ // Note: skip if using a dummy ExternalContext (one that is created
+ // before the FacesContext.
+ if (attr == null && key.equals("com.sun.faces.INVOCATION_PATH") &&
+ FacesContext.getCurrentInstance() != null)
{
// side effect of this will cause the viewid to be computed
// and this attribute to be set
Modified: myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java?rev=1451246&r1=1451245&r2=1451246&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java (original)
+++ myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java Thu Feb 28 16:22:58 2013
@@ -25,7 +25,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.portlet.ActionRequest;
import javax.portlet.PortletRequest;
+import javax.portlet.ResourceRequest;
import javax.portlet.faces.Bridge;
import javax.portlet.faces.BridgeUtil;
@@ -129,8 +131,8 @@ public class PortletRequestParameterMap
// this indicate that during an action/resource all non-public params are private params
Map <String, String[]> privateParams = mPortletRequest.getPrivateParameterMap();;
- if ((BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.ACTION_PHASE ||
- BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.RESOURCE_PHASE))
+ if (mPortletRequest instanceof ActionRequest ||
+ mPortletRequest instanceof ResourceRequest)
{
Map<String, String[]> allParams = mPortletRequest.getParameterMap();
Map<String, String[]> publicParams = mPortletRequest.getPublicParameterMap();
Modified: myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java?rev=1451246&r1=1451245&r2=1451246&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java (original)
+++ myfaces/portlet-bridge/core/branches/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java Thu Feb 28 16:22:58 2013
@@ -27,7 +27,9 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import javax.portlet.ActionRequest;
import javax.portlet.PortletRequest;
+import javax.portlet.ResourceRequest;
import javax.portlet.faces.Bridge;
import javax.portlet.faces.BridgeUtil;
@@ -164,8 +166,8 @@ public class PortletRequestParameterValu
// this indicate that during an action/resource all non-public params are private params
Map <String, String[]> privateParams = mPortletRequest.getPrivateParameterMap();
- if ((BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.ACTION_PHASE ||
- BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.RESOURCE_PHASE))
+ if (mPortletRequest instanceof ActionRequest ||
+ mPortletRequest instanceof ResourceRequest)
{
Map<String, String[]> allParams = mPortletRequest.getParameterMap();
Map<String, String[]> publicParams = mPortletRequest.getPublicParameterMap();