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 2010/03/18 23:30:25 UTC

svn commit: r925027 - in /myfaces/portlet-bridge/core/trunk_2.0.x: api/src/main/java/javax/portlet/faces/ impl/src/main/java/org/apache/myfaces/portlet/faces/application/ impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/ impl/src/main/java/or...

Author: mfreedman
Date: Thu Mar 18 22:30:25 2010
New Revision: 925027

URL: http://svn.apache.org/viewvc?rev=925027&view=rev
Log:
PORTLETBRIDGE-129: FacesContext.release() ConcurrentModificationException
PORTLETBRIDGE-130: getResponseCharacterEncoding and getResponseContentType fail 
PORTLETBRIDGE-131: Render redirect caused by JSF EL should return without flush/commit
PORTLETBRIDGE-132: Websphere: no private parameters in an action but we expect them
PORTLETBRIDGE-133: VIEWSTATE param encoded in the portlet:currentView URL when it shouldn't
PORTLETBRIDGE-134: Portlet 2.0 Bridge renders incorrectly if event follows a render 

Modified:
    myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeUtil.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/wrapper/BridgeRenderRequestWrapper.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletFacesContextImpl.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeUtil.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeUtil.java?rev=925027&r1=925026&r2=925027&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeUtil.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeUtil.java Thu Mar 18 22:30:25 2010
@@ -50,7 +50,7 @@ public class BridgeUtil
   
   /** Return describes the portlet request phase currently being executed.  If 
    * <code>null</code> then this request is not being executed in a portlet 
-   * container.
+   * container -- note this should never be called unless running within a Faces lifecyle in a portlet request.
    */
   public static Bridge.PortletPhase getPortletRequestPhase() 
   {

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java?rev=925027&r1=925026&r2=925027&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java Thu Mar 18 22:30:25 2010
@@ -346,6 +346,14 @@ public class PortletViewHandlerImpl exte
     doRenderView(context, viewToRender);
 
     newWriter.endDocument();
+    
+    // Check again to see if the processing of the Faces view triggered a redirect
+    redirectParams = (QueryString) context.getExternalContext()
+                      .getRequestMap().get(BridgeImpl.REDIRECT_VIEWPARAMS);
+    if ((redirectParams != null))
+    {
+      return;
+    }    
 
     // replace markers in the body content and write it to response.
 

Modified: myfaces/portlet-bridge/core/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/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java?rev=925027&r1=925026&r2=925027&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java Thu Mar 18 22:30:25 2010
@@ -513,7 +513,7 @@ public class BridgeImpl
 
     FacesContext context = null;
     Lifecycle lifecycle = null;
-    String scopeId = request.getParameter(REQUEST_SCOPE_ID_RENDER_PARAM);
+    String scopeId = getRequestScopeId(request);
     if (scopeId != null)
     {
       // Its possible we didn't detect the mode change but its the wrong scope
@@ -544,7 +544,12 @@ public class BridgeImpl
       }
    
       // 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);
@@ -577,6 +582,13 @@ public class BridgeImpl
         if (scopeId == null)
         {
           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?
         }
 
         // Before preserving the request scope data in the bridge's
@@ -731,7 +743,18 @@ public class BridgeImpl
       scopeId = getRequestScopeId(request);
     }
     
-    restoredScope = restoreBridgeRequestScopeData(request, scopeId);
+    if (scopeId != null)
+    { 
+      restoredScope = restoreBridgeRequestScopeData(request, scopeId);
+    }
+    else
+    {
+      // 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);
+    }
+    
 
     FacesContext context = null;
     try
@@ -921,11 +944,8 @@ public class BridgeImpl
       // Don't update if we have redirected during this render instead remove the scope
       if (!redirectedDuringRender)
       {
-        if (BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.RESOURCE_PHASE)
-        {
-          saveFacesMessageState(context);
-          saveBridgeRequestScopeData(context, scopeId, preExistingAttributes);
-        }
+        saveFacesMessageState(context);
+        saveBridgeRequestScopeData(context, scopeId, preExistingAttributes);
         updateViewInfo(context, scopeId);
       }
       else
@@ -1242,11 +1262,12 @@ public class BridgeImpl
     }
   }
   
+  @SuppressWarnings( "unchecked" )
   private ArrayList<String> getPublicParameterNamesList()
   {
     Enumeration<String> e = mPortletConfig.getPublicRenderParameterNames();
-    if (!e.hasMoreElements()) return (ArrayList<String>) Collections.EMPTY_LIST;
-    ArrayList<String>  l = new ArrayList<String>(10);
+    ArrayList<String>  l = new ArrayList<String>();
+    if (!e.hasMoreElements()) return l;
       
     while (e.hasMoreElements())
     {
@@ -1293,7 +1314,7 @@ public class BridgeImpl
     }
 
     // now wrap the request object to expose only those params as are in QS
-    return (RenderRequest) new BridgeRenderRequestWrapper(request, privateParamMap, publicParamMap, false);
+    return (RenderRequest) new BridgeRenderRequestWrapper(request, null, privateParamMap, publicParamMap, false);
   }
   
   private void updatePublicRedirectParams(PortletRequest request, QueryString redirectParams, Map<String, String[]> cachedPRPs)
@@ -1683,6 +1704,7 @@ public class BridgeImpl
 
   private String getRequestScopeId(PortletRequest request)
   {
+    boolean fromSession = false;
     String scopeId = request.getParameter(REQUEST_SCOPE_ID_RENDER_PARAM);
 
     if (scopeId == null)
@@ -1691,6 +1713,7 @@ public class BridgeImpl
       if (session != null)
       {
         scopeId = (String) session.getAttribute(BRIDGE_PACKAGE_PREFIX + REQUEST_SCOPE_ID_RENDER_PARAM);
+        fromSession = true;
       }
     }
     
@@ -1707,7 +1730,7 @@ public class BridgeImpl
         scopeId = null;
       }
     }
-    
+        
     return scopeId;
   }
 
@@ -1731,7 +1754,7 @@ public class BridgeImpl
     }
     else
     {
-      // Must be a resource request before a scope has been established
+      // Must be a render/resource request before a scope has been established
       // store in session until next action
       PortletSession session = request.getPortletSession(true);
       session.setAttribute(BRIDGE_PACKAGE_PREFIX + REQUEST_SCOPE_ID_RENDER_PARAM, requestScopeId);

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/wrapper/BridgeRenderRequestWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/wrapper/BridgeRenderRequestWrapper.java?rev=925027&r1=925026&r2=925027&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/wrapper/BridgeRenderRequestWrapper.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/wrapper/BridgeRenderRequestWrapper.java Thu Mar 18 22:30:25 2010
@@ -31,6 +31,7 @@ public class BridgeRenderRequestWrapper 
 {
   private Map<String, String[]> mPublicParamMap     = null;
   private Map<String, String[]> mPrivateParamMap     = null;
+  private Map<String, String[]> mInteractionParamMap     = null;
   private Map<String, String[]> mCombinedParamMap = null;
   private boolean mCombineParams = true;
   private boolean mPublicParamMapFixed = false; // if true contains all values and is unmodifyable
@@ -39,13 +40,14 @@ public class BridgeRenderRequestWrapper 
 
 
   public BridgeRenderRequestWrapper(RenderRequest request, 
-                                    Map<String, String[]> privateParams)
+                                    Map<String, String[]> interactionParams)
                                       throws IllegalArgumentException
   {
-    this(request, privateParams, null, true);
+    this(request, interactionParams, null, null, true);
   }
   
-  public BridgeRenderRequestWrapper(RenderRequest request, 
+  public BridgeRenderRequestWrapper(RenderRequest request,
+                                    Map<String, String[]> interactionParams,
                                     Map<String, String[]> privateParams,
                                     Map<String, String[]> publicParams,
                                     boolean combineParams)
@@ -55,8 +57,10 @@ public class BridgeRenderRequestWrapper 
 
     mPrivateParamMap = privateParams;
     mPublicParamMap = publicParams;
+    mInteractionParamMap = interactionParams;
     mCombinedParamMap = new LinkedHashMap<String, String[]>((mPublicParamMap != null) ? mPublicParamMap : Collections.EMPTY_MAP);
     mCombinedParamMap.putAll((mPrivateParamMap != null) ?  mPrivateParamMap : Collections.EMPTY_MAP);
+    mCombinedParamMap.putAll((mInteractionParamMap != null) ?  mInteractionParamMap : Collections.EMPTY_MAP);
     mCombineParams = combineParams;
   }
 

Modified: myfaces/portlet-bridge/core/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/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java?rev=925027&r1=925026&r2=925027&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java Thu Mar 18 22:30:25 2010
@@ -1411,7 +1411,7 @@ public class PortletExternalContextImpl
   @Override
   public String getResponseCharacterEncoding()
   {
-    if (getPortletPhase() != null && mPortletRequest instanceof MimeResponse)
+    if (!(mPortletResponse instanceof MimeResponse))
     {
       throw new IllegalStateException("PortletExternalContextImpl.getResponseCharacterEncoding(): Response must be a MimeResponse");
     }
@@ -1446,7 +1446,7 @@ public class PortletExternalContextImpl
   @Override
   public String getResponseContentType()
   {
-    if (getPortletPhase() != null && mPortletRequest instanceof MimeResponse)
+    if (!(mPortletResponse instanceof MimeResponse))
     {
       throw new IllegalStateException("PortletExternalContextImpl.getResponseContentType(): Response must be a MimeResponse");
     }

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletFacesContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletFacesContextImpl.java?rev=925027&r1=925026&r2=925027&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletFacesContextImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletFacesContextImpl.java Thu Mar 18 22:30:25 2010
@@ -26,6 +26,10 @@ import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 
+import java.util.Map;
+
+import java.util.Set;
+
 import javax.el.ELContext;
 import javax.el.ELContextEvent;
 import javax.el.ELContextListener;
@@ -48,6 +52,7 @@ import javax.portlet.PortletRequest;
 import javax.portlet.PortletResponse;
 import javax.portlet.faces.Bridge;
 import javax.portlet.faces.annotation.PortletNamingContainer;
+import javax.portlet.faces.BridgeUtil;
 
 import org.apache.myfaces.portlet.faces.bridge.BridgeImpl;
 import org.apache.myfaces.portlet.faces.el.PortletELContextImpl;
@@ -334,15 +339,24 @@ public class PortletFacesContextImpl ext
     // This is done because some (local) portals run/render all portlets in the same request
     PortletRequest request = (PortletRequest)mExternalContext.getRequest();
     List<String> preExistingAttrs = (List<String>) request.getAttribute(BridgeImpl.PREEXISTING_ATTRIBUTE_NAMES);
+    ArrayList<String> removeList = (ArrayList<String>) new ArrayList(preExistingAttrs.size());
     Enumeration<String> e = request.getAttributeNames();
     while (e.hasMoreElements())
     {
       String name = e.nextElement();
       if (!preExistingAttrs.contains(name))
       {
-        request.removeAttribute(name);
+        // Postpone the remove until after the iteration as it causes a ConcurrentModificationException on some appServers (WebSphere)
+        removeList.add(name);
       }
     }
+    
+    // Postpone the remove until after the iteration as it causes a ConcurrentModificationException on some appServers (WebSphere)
+    for(Iterator<String> iter = removeList.iterator(); iter.hasNext();)
+    {
+      request.removeAttribute(iter.next());
+    }
+
     if (mExternalContext != null && mExternalContext instanceof PortletExternalContextImpl)
     {
       ((PortletExternalContextImpl) mExternalContext).release();
@@ -362,6 +376,7 @@ public class PortletFacesContextImpl ext
   {
     mRenderResponse = true;
   }
+  
 
   @Override
   public void responseComplete()

Modified: myfaces/portlet-bridge/core/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/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java?rev=925027&r1=925026&r2=925027&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterMap.java Thu Mar 18 22:30:25 2010
@@ -27,6 +27,9 @@ import java.util.Map;
 
 import javax.portlet.PortletRequest;
 
+import javax.portlet.faces.Bridge;
+import javax.portlet.faces.BridgeUtil;
+
 /**
  * Map of portlet request params
  */
@@ -63,7 +66,7 @@ public class PortletRequestParameterMap 
     {  
       if (mPrivateParameters == null) 
       {
-        mPrivateParameters = mPortletRequest.getPrivateParameterMap();
+        mPrivateParameters = getPrivateParameterMap();
       }
       String[] params = mPrivateParameters.get(key);
       if (params != null)
@@ -106,7 +109,7 @@ public class PortletRequestParameterMap 
 
       if (mPrivateParameters == null) 
       {
-        mPrivateParameters = mPortletRequest.getPrivateParameterMap();
+        mPrivateParameters = getPrivateParameterMap();
       }
       attrNames.addAll(mPrivateParameters.keySet());
       attrNames.addAll(mInternalAttributes.keySet());
@@ -118,4 +121,39 @@ public class PortletRequestParameterMap 
       throw new IllegalArgumentException(ILLEGAL_ARGUMENT);
     }
   }
+  
+  private Map<String,String[]> getPrivateParameterMap()
+  {
+    // Some portlet containers (WebSphere) claim there are no private parameters 
+    // during an action -- instead they are all regular params -- to workaround
+    // this indicate that during an action all non-public params are private params
+    
+    // For other phases rely on the portlet api to get the private param map
+    if (BridgeUtil.getPortletRequestPhase() != Bridge.PortletPhase.ACTION_PHASE)
+    {
+      return mPortletRequest.getPrivateParameterMap();
+    }
+    
+    Map<String, String[]> allParams = mPortletRequest.getParameterMap();
+    Map<String, String[]> publicParams = mPortletRequest.getPublicParameterMap();
+    Map<String, String[]> privateParams = null;
+    
+    if (publicParams.size() == 0)
+    {
+      privateParams = allParams;
+    }
+    else
+    {
+      // Construct the non-Public param Map by excluding those which are public
+      // from the overall set.  This works around issue that some portlet
+      // containers think getPrivateParameters shoudl return the private
+      // render parameters -- and hence its empty during an action. (WebSphere 6.1 is one case)
+      privateParams = (Map<String, String[]>) new HashMap(allParams);
+      for (Map.Entry<String, String[]> entry :  publicParams.entrySet())
+      {
+        privateParams.remove(entry.getKey());
+      }
+    }
+    return privateParams;
+  }
 }

Modified: myfaces/portlet-bridge/core/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/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java?rev=925027&r1=925026&r2=925027&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/map/PortletRequestParameterValuesMap.java Thu Mar 18 22:30:25 2010
@@ -29,6 +29,9 @@ import java.util.Map;
 
 import javax.portlet.PortletRequest;
 
+import javax.portlet.faces.Bridge;
+import javax.portlet.faces.BridgeUtil;
+
 /**
  * Map of portlet request param values
  */
@@ -99,7 +102,7 @@ public class PortletRequestParameterValu
     {
       if (mPrivateParametersMap == null)
       {
-         mPrivateParametersMap =  mPortletRequest.getPrivateParameterMap();
+         mPrivateParametersMap =  getPrivateParameterMap();
       }
       String[] params = mPrivateParametersMap.get(key);
       if (params != null)
@@ -140,7 +143,7 @@ public class PortletRequestParameterValu
       
       if (mPrivateParametersMap == null) 
       {
-        mPrivateParametersMap = mPortletRequest.getPrivateParameterMap();
+        mPrivateParametersMap = getPrivateParameterMap();
       }
 
       attrNames.addAll(mPrivateParametersMap.keySet());
@@ -153,4 +156,39 @@ public class PortletRequestParameterValu
       throw new IllegalArgumentException(ILLEGAL_ARGUMENT);
     }
   }
+  
+  private Map<String,String[]> getPrivateParameterMap()
+  {
+    // Some portlet containers (WebSphere) claim there are no private parameters 
+    // during an action -- instead they are all regular params -- to workaround
+    // this indicate that during an action all non-public params are private params
+    
+    // For other phases rely on the portlet api to get the private param map
+    if (BridgeUtil.getPortletRequestPhase() != Bridge.PortletPhase.ACTION_PHASE)
+    {
+      return mPortletRequest.getPrivateParameterMap();
+    }
+    
+    Map<String, String[]> allParams = mPortletRequest.getParameterMap();
+    Map<String, String[]> publicParams = mPortletRequest.getPublicParameterMap();
+    Map<String, String[]> privateParams = null;
+    
+    if (publicParams.size() == 0)
+    {
+      privateParams = allParams;
+    }
+    else
+    {
+      // Construct the non-Public param Map by excluding those which are public
+      // from the overall set.  This works around issue that some portlet
+      // containers think getPrivateParameters shoudl return the private
+      // render parameters -- and hence its empty during an action. (WebSphere 6.1 is one case)
+      privateParams = (Map<String, String[]>) new HashMap(allParams);
+      for (Map.Entry<String, String[]> entry :  publicParams.entrySet())
+      {
+        privateParams.remove(entry.getKey());
+      }
+    }
+    return privateParams;
+  }
 }