myfaces-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mfreed...@apache.org
Subject svn commit: r982807 - 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...
Date Thu, 05 Aug 2010 22:22:11 GMT
Author: mfreedman
Date: Thu Aug  5 22:22:10 2010
New Revision: 982807

URL: http://svn.apache.org/viewvc?rev=982807&view=rev
Log:
PORTLETBRIDGE-165: Bridge explicit scope removal doesn't cause its attributes to be notified
but should
PORTLETBRIDGE-164: Bridge shouldn't notify (bridge) request scope attributes that they are
being destroyed if only updating the scope at the end of a request
PORTLETBRIDGE-163: Portlet 2.0 Bridge should establish child request scopes if rendering a
resource from a different view (in an iFrame)
PORTLETBRIDGE-162: Portlet 2.0 Bridge: Resource as source of iFrame doesn't render in Pluto
PORTLETBRIDGE-161: Portlet 2.0 Bridge doesn't properly encode portlet:resource syntax to a
faces View
PORTLETBRIDGE-160: QueryString.numParameters throws NullPointerException
PORTLETBRIDGE-159: Race condition in GenericFacesPortlet: mFacesBridge 

Added:
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/BridgeViewHandlerRenderResponseWrapper.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/BridgeViewHandlerResourceResponseWrapper.java
Modified:
    myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeWriteBehindResponse.java
    myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.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/context/PortletExternalContextImpl.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeWriteBehindResponse.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeWriteBehindResponse.java?rev=982807&r1=982806&r2=982807&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeWriteBehindResponse.java
(original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeWriteBehindResponse.java
Thu Aug  5 22:22:10 2010
@@ -10,6 +10,8 @@
  */
 package javax.portlet.faces;
 
+import java.io.IOException;
+
 import javax.faces.context.FacesContext;
 import javax.portlet.Event;
 import javax.portlet.faces.event.EventNavigationResult;
@@ -70,4 +72,15 @@ public interface BridgeWriteBehindRespon
    * @return the response as a byte[].
    */ 
   public byte[] getBytes();
+  
+  /**
+   * Called by the bridge after dispatching to flush the current buffered content to the
wrapped
+   * response (this could be a Servlet or Portlet response).  This is done in a situation
where
+   * we aren't supporting writeBehind behavior.  We stil use a wrapped/buffered response
because we use 
+   * dispatch.forward which in many environments closes the writer at the end of the forward.
 If not
+   * wrapped, not further writing to the output would be feasible.
+   * @throws IOException if content cannot be written
+   */
+  public void flushContentToWrappedResponse()
+    throws IOException;  
 }

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java?rev=982807&r1=982806&r2=982807&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
(original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
Thu Aug  5 22:22:10 2010
@@ -204,7 +204,9 @@ public class GenericFacesPortlet extends
                                        Bridge.BRIDGE_PUBLIC_RENDER_PARAMETER_HANDLER, prpHandler);
     }
 
-    // Don't instanciate/initialize the bridge yet. Do it on first use
+    // Initialize the bridge as the double lock mechanism used for lazy instantiation doesn't
(always) work in Java even if 
+    // declared a volitle -- and the bridge is likely to be used anyway -- so why worry about
it
+    initBridge();
   }
 
   /**
@@ -739,9 +741,6 @@ public class GenericFacesPortlet extends
   private void initBridgeRequest(PortletRequest request, 
                                  PortletResponse response) throws PortletException
   {
-    initBridge();
-
-
     // Now do any per request initialization
     // In this case look to see if the request is encoded (usually 
     // from a NonFaces view response) with the specific Faces
@@ -768,13 +767,10 @@ public class GenericFacesPortlet extends
       try
       {
         // ensure we only ever create/init one bridge per portlet
-        synchronized(mLock)
+        if (mFacesBridge == null)
         {
-          if (mFacesBridge == null)
-          {
-            mFacesBridge = mFacesBridgeClass.newInstance();
-            mFacesBridge.init(getPortletConfig());
-          }
+          mFacesBridge = mFacesBridgeClass.newInstance();
+          mFacesBridge.init(getPortletConfig());
         }
       }
       catch (Exception e)

Added: myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/BridgeViewHandlerRenderResponseWrapper.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/BridgeViewHandlerRenderResponseWrapper.java?rev=982807&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/BridgeViewHandlerRenderResponseWrapper.java
(added)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/BridgeViewHandlerRenderResponseWrapper.java
Thu Aug  5 22:22:10 2010
@@ -0,0 +1,339 @@
+/* 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 org.apache.myfaces.portlet.faces.application;
+
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import java.nio.ByteBuffer;
+
+import javax.faces.context.FacesContext;
+
+import javax.portlet.RenderResponse;
+
+import javax.portlet.filter.RenderResponseWrapper;
+
+import javax.servlet.http.HttpServletResponse;
+
+import javax.portlet.faces.BridgeWriteBehindResponse;
+
+
+public class BridgeViewHandlerRenderResponseWrapper
+  extends RenderResponseWrapper
+  implements BridgeWriteBehindResponse
+{
+
+  private DirectByteArrayServletOutputStream mByteStream;
+  private CharArrayWriter mCharWriter;
+  private PrintWriter mPrintWriter;
+  private int mStatus = HttpServletResponse.SC_OK;
+  
+  public BridgeViewHandlerRenderResponseWrapper()
+  {
+    super((RenderResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse());
+  }
+
+
+  public BridgeViewHandlerRenderResponseWrapper(RenderResponse wrapped)
+  {
+    super(wrapped);
+  }
+
+  public void flushBuffer()
+  {
+    if (isChars())
+    {
+      mPrintWriter.flush();
+    }
+  }
+
+  public int getBufferSize()
+  {
+    if (isBytes())
+    {
+      return mByteStream.size();
+    }
+    else if (isChars())
+    {
+      return mCharWriter.size();
+    }
+    else
+      return 0;
+  }
+
+
+  public void reset()
+  {
+    super.reset();
+    if (isBytes())
+    {
+      mByteStream.reset();
+    }
+    else if (isChars())
+    {
+      mPrintWriter.flush();
+      mCharWriter.reset();
+    }
+  }
+
+  public void resetBuffer()
+  {
+    super.resetBuffer();
+    if (isBytes())
+    {
+      mByteStream.reset();
+    }
+    else if (isChars())
+    {
+      mPrintWriter.flush();
+      mCharWriter.reset();
+    }
+  }
+
+
+  public OutputStream getPortletOutputStream()
+    throws IOException
+  {
+    if (mPrintWriter != null)
+    {
+      throw new IllegalStateException();
+    }
+    if (mByteStream == null)
+    {
+      mByteStream = new DirectByteArrayServletOutputStream();
+    }
+    return mByteStream;
+  }
+
+  public PrintWriter getWriter()
+    throws IOException
+  {
+    if (mByteStream != null)
+    {
+      throw new IllegalStateException();
+    }
+    if (mPrintWriter == null)
+    {
+      mCharWriter = new CharArrayWriter(4096);
+      mPrintWriter = new PrintWriter(mCharWriter);
+    }
+
+    return mPrintWriter;
+  }
+
+  public int getStatus()
+  {
+    return mStatus;
+  }
+
+  public boolean isBytes()
+  {
+    return (mByteStream != null);
+  }
+
+  public boolean isChars()
+  {
+    return (mCharWriter != null);
+  }
+
+  public byte[] getBytes()
+  {
+    if (isBytes())
+    {
+      return mByteStream.toByteArray();
+    }
+    else
+    {
+      return null;
+    }
+  }
+
+  public char[] getChars()
+  {
+    if (isChars())
+    {
+      mCharWriter.flush();
+      return mCharWriter.toCharArray();
+    }
+    else
+    {
+      return null;
+    }
+  }
+
+  public String toString()
+  {
+    if (isChars())
+    {
+      mCharWriter.flush();
+      return mCharWriter.toString();
+    }
+    else if (isBytes())
+    {
+      return mByteStream.toString();
+    }
+    else
+      return null;
+  }
+
+  public void clearWrappedResponse()
+    throws IOException
+  {
+    resetBuffers();
+  }
+
+  /**
+   * Flush the current buffered content to the wrapped
+   * response (this could be a Servlet or Portlet response)
+   * @throws IOException if content cannot be written
+   */
+  public void flushContentToWrappedResponse()
+    throws IOException
+  {
+    RenderResponse response = getResponse();
+
+    flushBuffer();
+
+    if (isBytes())
+    {
+      response.getPortletOutputStream().write(getBytes());
+      mByteStream.reset();
+    }
+    else if (isChars())
+    {
+      response.getWriter().write(getChars());
+      mCharWriter.reset();
+    }
+
+  }
+
+  /**
+   * Flush the current buffered content to the provided <code>Writer</code>
+   * @param writer target <code>Writer</code>
+   * @param encoding the encoding that should be used
+   * @throws IOException if content cannot be written
+   */
+  public void flushToWriter(Writer writer, String encoding)
+    throws IOException
+  {
+    flushBuffer();
+
+    if (isBytes())
+    {
+      throw new IOException("Invalid flushToWriter as the code is writing bytes to an OutputStream.");
+    }
+    else if (isChars())
+    {
+      writer.write(getChars());
+      mCharWriter.reset();
+    }
+  }
+
+  /**
+   * Clear the internal buffers.
+   * @throws IOException if some odd error occurs
+   */
+  public void resetBuffers()
+    throws IOException
+  {
+    if (isBytes())
+    {
+      mByteStream.reset();
+    }
+    else if (isChars())
+    {
+      mPrintWriter.flush();
+      mCharWriter.reset();
+    }
+  }
+
+
+  // ----------------------------------------------------------- Inner Classes
+
+
+  private class DirectByteArrayServletOutputStream
+    extends OutputStream
+  {
+    private DirectByteArrayOutputStream mByteArrayOutputStream;
+
+    public DirectByteArrayServletOutputStream()
+    {
+      mByteArrayOutputStream = new DirectByteArrayOutputStream(4096);
+    }
+
+    public void write(int n)
+    {
+      mByteArrayOutputStream.write(n);
+    }
+
+    public byte[] toByteArray()
+    {
+      return mByteArrayOutputStream.toByteArray();
+    }
+
+    public int size()
+    {
+      return mByteArrayOutputStream.size();
+    }
+
+    public void reset()
+    {
+      mByteArrayOutputStream.reset();
+    }
+
+  }
+
+
+  private class DirectByteArrayOutputStream
+    extends ByteArrayOutputStream
+  {
+
+
+    // -------------------------------------------------------- Constructors
+
+
+    public DirectByteArrayOutputStream(int initialCapacity)
+    {
+      super(initialCapacity);
+    }
+
+
+    // ------------------------------------------------------- PublicMethods
+
+
+    /**
+     * Return the buffer backing this ByteArrayOutputStream as a 
+     * ByteBuffer.
+     * @return buf wrapped in a ByteBuffer
+     */
+    public ByteBuffer getByteBuffer()
+    {
+      return (ByteBuffer.wrap(buf, 0, count));
+    }
+
+  }
+
+
+  // end of class BridgeRenderFilterResponseWrapper
+}

Added: myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/BridgeViewHandlerResourceResponseWrapper.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/BridgeViewHandlerResourceResponseWrapper.java?rev=982807&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/BridgeViewHandlerResourceResponseWrapper.java
(added)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/BridgeViewHandlerResourceResponseWrapper.java
Thu Aug  5 22:22:10 2010
@@ -0,0 +1,339 @@
+/* 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 org.apache.myfaces.portlet.faces.application;
+
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import java.nio.ByteBuffer;
+
+import javax.faces.context.FacesContext;
+
+import javax.portlet.ResourceResponse;
+
+import javax.portlet.filter.ResourceResponseWrapper;
+
+import javax.servlet.http.HttpServletResponse;
+
+import javax.portlet.faces.BridgeWriteBehindResponse;
+
+
+public class BridgeViewHandlerResourceResponseWrapper
+  extends ResourceResponseWrapper
+  implements BridgeWriteBehindResponse
+{
+
+  private DirectByteArrayServletOutputStream mByteStream;
+  private CharArrayWriter mCharWriter;
+  private PrintWriter mPrintWriter;
+  private int mStatus = HttpServletResponse.SC_OK;
+  
+  public BridgeViewHandlerResourceResponseWrapper()
+  {
+    super((ResourceResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse());
+  }
+
+
+  public BridgeViewHandlerResourceResponseWrapper(ResourceResponse wrapped)
+  {
+    super(wrapped);
+  }
+
+  public void flushBuffer()
+  {
+    if (isChars())
+    {
+      mPrintWriter.flush();
+    }
+  }
+
+  public int getBufferSize()
+  {
+    if (isBytes())
+    {
+      return mByteStream.size();
+    }
+    else if (isChars())
+    {
+      return mCharWriter.size();
+    }
+    else
+      return 0;
+  }
+
+
+  public void reset()
+  {
+    super.reset();
+    if (isBytes())
+    {
+      mByteStream.reset();
+    }
+    else if (isChars())
+    {
+      mPrintWriter.flush();
+      mCharWriter.reset();
+    }
+  }
+
+  public void resetBuffer()
+  {
+    super.resetBuffer();
+    if (isBytes())
+    {
+      mByteStream.reset();
+    }
+    else if (isChars())
+    {
+      mPrintWriter.flush();
+      mCharWriter.reset();
+    }
+  }
+
+
+  public OutputStream getPortletOutputStream()
+    throws IOException
+  {
+    if (mPrintWriter != null)
+    {
+      throw new IllegalStateException();
+    }
+    if (mByteStream == null)
+    {
+      mByteStream = new DirectByteArrayServletOutputStream();
+    }
+    return mByteStream;
+  }
+
+  public PrintWriter getWriter()
+    throws IOException
+  {
+    if (mByteStream != null)
+    {
+      throw new IllegalStateException();
+    }
+    if (mPrintWriter == null)
+    {
+      mCharWriter = new CharArrayWriter(4096);
+      mPrintWriter = new PrintWriter(mCharWriter);
+    }
+
+    return mPrintWriter;
+  }
+
+  public int getStatus()
+  {
+    return mStatus;
+  }
+
+  public boolean isBytes()
+  {
+    return (mByteStream != null);
+  }
+
+  public boolean isChars()
+  {
+    return (mCharWriter != null);
+  }
+
+  public byte[] getBytes()
+  {
+    if (isBytes())
+    {
+      return mByteStream.toByteArray();
+    }
+    else
+    {
+      return null;
+    }
+  }
+
+  public char[] getChars()
+  {
+    if (isChars())
+    {
+      mCharWriter.flush();
+      return mCharWriter.toCharArray();
+    }
+    else
+    {
+      return null;
+    }
+  }
+
+  public String toString()
+  {
+    if (isChars())
+    {
+      mCharWriter.flush();
+      return mCharWriter.toString();
+    }
+    else if (isBytes())
+    {
+      return mByteStream.toString();
+    }
+    else
+      return null;
+  }
+
+  public void clearWrappedResponse()
+    throws IOException
+  {
+    resetBuffers();
+  }
+
+  /**
+   * Flush the current buffered content to the wrapped
+   * response (this could be a Servlet or Portlet response)
+   * @throws IOException if content cannot be written
+   */
+  public void flushContentToWrappedResponse()
+    throws IOException
+  {
+    ResourceResponse response = getResponse();
+
+    flushBuffer();
+
+    if (isBytes())
+    {
+      response.getPortletOutputStream().write(getBytes());
+      mByteStream.reset();
+    }
+    else if (isChars())
+    {
+      response.getWriter().write(getChars());
+      mCharWriter.reset();
+    }
+
+  }
+
+  /**
+   * Flush the current buffered content to the provided <code>Writer</code>
+   * @param writer target <code>Writer</code>
+   * @param encoding the encoding that should be used
+   * @throws IOException if content cannot be written
+   */
+  public void flushToWriter(Writer writer, String encoding)
+    throws IOException
+  {
+    flushBuffer();
+
+    if (isBytes())
+    {
+      throw new IOException("Invalid flushToWriter as the code is writing bytes to an OutputStream.");
+    }
+    else if (isChars())
+    {
+      writer.write(getChars());
+      mCharWriter.reset();
+    }
+  }
+
+  /**
+   * Clear the internal buffers.
+   * @throws IOException if some odd error occurs
+   */
+  public void resetBuffers()
+    throws IOException
+  {
+    if (isBytes())
+    {
+      mByteStream.reset();
+    }
+    else if (isChars())
+    {
+      mPrintWriter.flush();
+      mCharWriter.reset();
+    }
+  }
+
+
+  // ----------------------------------------------------------- Inner Classes
+
+
+  private class DirectByteArrayServletOutputStream
+    extends OutputStream
+  {
+    private DirectByteArrayOutputStream mByteArrayOutputStream;
+
+    public DirectByteArrayServletOutputStream()
+    {
+      mByteArrayOutputStream = new DirectByteArrayOutputStream(4096);
+    }
+
+    public void write(int n)
+    {
+      mByteArrayOutputStream.write(n);
+    }
+
+    public byte[] toByteArray()
+    {
+      return mByteArrayOutputStream.toByteArray();
+    }
+
+    public int size()
+    {
+      return mByteArrayOutputStream.size();
+    }
+
+    public void reset()
+    {
+      mByteArrayOutputStream.reset();
+    }
+
+  }
+
+
+  private class DirectByteArrayOutputStream
+    extends ByteArrayOutputStream
+  {
+
+
+    // -------------------------------------------------------- Constructors
+
+
+    public DirectByteArrayOutputStream(int initialCapacity)
+    {
+      super(initialCapacity);
+    }
+
+
+    // ------------------------------------------------------- PublicMethods
+
+
+    /**
+     * Return the buffer backing this ByteArrayOutputStream as a 
+     * ByteBuffer.
+     * @return buf wrapped in a ByteBuffer
+     */
+    public ByteBuffer getByteBuffer()
+    {
+      return (ByteBuffer.wrap(buf, 0, count));
+    }
+
+  }
+
+
+  // end of class BridgeRenderFilterResponseWrapper
+}

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=982807&r1=982806&r2=982807&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 Aug  5 22:22:10 2010
@@ -438,6 +438,8 @@ public class PortletViewHandlerImpl exte
                                           UIViewRoot viewToRender)
       throws IOException
   {
+      boolean writeBehind = false;
+      
       String viewURI = viewToRender.getViewId();
 
       // update the JSTL locale attribute in request scope so that JSTL
@@ -460,6 +462,7 @@ public class PortletViewHandlerImpl exte
           if (wrapped instanceof PortletResponseWrapper)
           {
             extContext.setResponse(wrapped);
+            writeBehind = true;
           }
           else
           {
@@ -473,7 +476,21 @@ public class PortletViewHandlerImpl exte
           // Just warn and don't use;
           ((PortletContext)extContext.getContext()).log("Unable to instantiate configured
BridgeWriteBehindResponse instance: ", e);
         }
-      }      
+      } 
+      else
+      {
+        // Use the generic (non-writeBehindResponse) wrapper 
+        if (BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.RENDER_PHASE)
+        {
+          wrapped = new BridgeViewHandlerRenderResponseWrapper();
+        }
+        else
+        {
+          wrapped = new BridgeViewHandlerResourceResponseWrapper();
+        }
+        extContext.setResponse(wrapped);
+        // don't set write behind as this one doesn't support the Faces specific implementation
dependent interfaces
+      }
       // set request attribute indicating we can deal with content
       // that is supposed to be delayed until after JSF tree is ouput.
       extContext.getRequestMap().put(Bridge.RENDER_CONTENT_AFTER_VIEW, Boolean.TRUE);
@@ -487,13 +504,22 @@ public class PortletViewHandlerImpl exte
         // replace the original response
         extContext.setResponse(originalResponse);
         
-        // Put the AFTER_VIEW_CONTENT into request scope
-        // temporarily    
-        Object o = (wrapped.isChars()) ? (Object) wrapped.getChars() : (Object) wrapped.getBytes();
-
-        if (o != null)
+        if (writeBehind)
+        {
+          // Put the AFTER_VIEW_CONTENT into request scope
+          // temporarily    
+          Object o = (wrapped.isChars()) ? (Object) wrapped.getChars() : (Object) wrapped.getBytes();
+        
+          // only write if a filter hasn't already written
+          if (o != null && extContext.getRequestMap().get(Bridge.AFTER_VIEW_CONTENT)
== null)
+          {
+            extContext.getRequestMap().put(Bridge.AFTER_VIEW_CONTENT, o);
+          }
+        }
+        else
         {
-          extContext.getRequestMap().put(Bridge.AFTER_VIEW_CONTENT, o);
+          // write ahead -- just write this to the restored response
+          wrapped.flushContentToWrappedResponse();
         }
       } 
   }

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=982807&r1=982806&r2=982807&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 Aug  5 22:22:10 2010
@@ -40,6 +40,8 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
+import java.util.Vector;
+
 import javax.el.ELContext;
 import javax.el.ELContextEvent;
 import javax.el.ELContextListener;
@@ -132,6 +134,7 @@ public class BridgeImpl
 
   private static final String REQUEST_SCOPE_LOCK = "org.apache.myfaces.portlet.faces.requestScopeLock";
   private static final String REQUEST_SCOPE_MAP = "org.apache.myfaces.portlet.faces.requestScopeMap";
+  private static final String CHILD_RESOURCE_REQUEST_SCOPE_MAP = "org.apache.myfaces.portlet.faces.includeInScope.childResourceRequestScopeMap";
   private static final String REQUEST_SCOPE_LISTENER = "org.apache.myfaces.portlet.faces.requestScopeWatch";
   public static final String FACES_VIEWROOT = "org.apache.myfaces.portlet.faces.includeInScope.facesViewRoot";
   private static final String FACES_MESSAGES = "org.apache.myfaces.portlet.faces.includeInScope.facesMessages";
@@ -1013,7 +1016,7 @@ public class BridgeImpl
     request.setAttribute(Bridge.PORTLET_LIFECYCLE_PHASE, Bridge.PortletPhase.RESOURCE_PHASE);
 
     // Determine whether this is a Faces resource or a regular one.
-    if (request.getParameter(PortletExternalContextImpl.JSF_RESOURCE_TARGET_VIEWID_RENDER_PARAMETER)
== null)
+    if (!isFacesResourceRequest(request))
     {
       try
       {
@@ -1070,16 +1073,8 @@ public class BridgeImpl
     // needed request attributes.
     List<String> preExistingAttributes = getRequestAttributes(request);
 
-    String scopeId = getRequestScopeId(request);
-    if (scopeId == null)
-    {
-      // first request is a resource request
-      // create a scope and store in the session until an action occurs
-      // pass null as we aren't a StateAwareResponse
-      scopeId = initBridgeRequestScope(request, null);
-    }
-
     FacesContext context = null;
+    String scopeId = null;
     try
     {
       // Get the FacesContext instance for this request
@@ -1090,6 +1085,12 @@ public class BridgeImpl
       // Use request from ExternalContext in case its been wrapped by an
       // extension
       ResourceRequest extRequest = (ResourceRequest) extCtx.getRequest();
+      
+      // getting the scopeId is delayed until after getting the FacesContext
+      // because a resource request could be as a result of an embedded iFrame
+      // i.e. a child scope of the original render -- in this case don't use the render
+      // scope but the correct one contained within it
+      scopeId = getResourceRequestScopeId(extCtx, request);
 
       // ensure that isPostback attribute set if VIEW_STATE param exists
       if (extCtx.getRequestParameterValuesMap().containsKey(ResponseStateManager.VIEW_STATE_PARAM))
@@ -1122,6 +1123,13 @@ public class BridgeImpl
       request.removeAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
     }
   }
+  
+  private boolean isFacesResourceRequest(ResourceRequest request)
+  {
+    return (request.getParameter(PortletExternalContextImpl.JSF_TARGET_VIEWID_RENDER_PARAMETER)
!= null ||
+            request.getParameter(Bridge.FACES_VIEW_ID_PARAMETER) != null ||
+            request.getParameter(Bridge.FACES_VIEW_PATH_PARAMETER) != null);
+  }
 
 
   public void destroy()
@@ -1758,6 +1766,53 @@ public class BridgeImpl
       }
     }
   }
+  
+  private String getResourceRequestScopeId(ExternalContext extCtx, PortletRequest request)
+  {
+
+    // get the render scope this resource request is contained in
+    String scopeId = getRequestScopeId(request);
+       
+    if (scopeId == null)
+    {
+      // first request is a resource request
+      // create a scope and store in the session until an action occurs
+      // pass null as we aren't a StateAwareResponse
+      return initBridgeRequestScope(request, null);
+    }
+    
+    // Check to see if this resource request is targeting the same view or a different one
+    Map<String, Object> m = getScopeMap(scopeId);
+    Map<String, String> childResourceScopeMap = (Map<String, String>) m.get(CHILD_RESOURCE_REQUEST_SCOPE_MAP);
+    String scopeIdKey = null;
+    String childScopeId = null;
+    String pathInfo = extCtx.getRequestPathInfo();
+    String servletPath = extCtx.getRequestServletPath();
+    
+    if (pathInfo == null) scopeIdKey = servletPath;
+    else if (servletPath == null) scopeIdKey = pathInfo;
+    else scopeIdKey = servletPath + pathInfo;
+
+    if (childResourceScopeMap != null)
+    {
+      childScopeId = childResourceScopeMap.get(scopeIdKey);
+    }
+    
+    if (childScopeId == null)
+    {
+      childScopeId = createBridgeRequestScope(request);
+      
+      if (childResourceScopeMap == null)
+      {
+        childResourceScopeMap = (Map<String, String>) new HashMap(3); 
+        m.put(CHILD_RESOURCE_REQUEST_SCOPE_MAP, childResourceScopeMap);
+      }
+      childResourceScopeMap.put(scopeIdKey, childScopeId);
+    }
+        
+    return childScopeId;
+  }  
+  
 
   private String getRequestScopeId(PortletRequest request)
   {
@@ -1790,18 +1845,26 @@ public class BridgeImpl
         
     return scopeId;
   }
-
-  private String initBridgeRequestScope(PortletRequest request, StateAwareResponse response)
+  
+  private String createBridgeRequestScope(PortletRequest request)
   {
 
     // Generate an RMI UID, which is a unique identifier WITHIN the local
     // host. This will be used as the new lifecyleID
     UID uid = new UID();
-    String requestScopeId = qualifyScopeId(mPortletConfig.getPortletName(),
+    return qualifyScopeId(mPortletConfig.getPortletName(),
                                            request.getPortletSession(true).getId(),
                                            request.getPortletMode().toString(),
                                            uid.toString());
 
+  }
+
+  private String initBridgeRequestScope(PortletRequest request, StateAwareResponse response)
+  {
+
+
+    String requestScopeId = createBridgeRequestScope(request);
+
     if (response != null)
     {
       // set in response render parameter so will receive in future calls
@@ -1973,13 +2036,32 @@ public class BridgeImpl
     }
     return false;
   }
+  
+  @SuppressWarnings("unchecked")
+  private Map<String, Object> getScopeMap(String scopeId)
+  {
+    PortletContext portletContext = mPortletConfig.getPortletContext();
+
+    // Get the data from the scope
+    synchronized (portletContext.getAttribute(REQUEST_SCOPE_LOCK))
+    {
+      // get the managedScopeMap
+      LRUMap requestScopeMap = (LRUMap) portletContext.getAttribute(REQUEST_SCOPE_MAP);
+      // No scope for all renders before first action to this portletApp
+      if (requestScopeMap == null)
+      {
+        return null;
+      }
+
+      return requestScopeMap.get(scopeId);
+    }
+  }
 
   @SuppressWarnings("unchecked")
   private boolean restoreBridgeRequestScopeData(PortletRequest request, String scopeId)
     throws BridgeException
   {
 
-    PortletContext portletContext = mPortletConfig.getPortletContext();
     Map<String, Object> m;
     
     //TODO: Since this is a private method, is it easier to ensure scope id is not null here
thus replacing this with
@@ -1988,23 +2070,12 @@ public class BridgeImpl
     {
       return false;
     }
+    
+    m = getScopeMap(scopeId);
 
-    // Get the data from the scope
-    synchronized (portletContext.getAttribute(REQUEST_SCOPE_LOCK))
+    if (m == null)
     {
-      // get the managedScopeMap
-      LRUMap requestScopeMap = (LRUMap) portletContext.getAttribute(REQUEST_SCOPE_MAP);
-      // No scope for all renders before first action to this portletApp
-      if (requestScopeMap == null)
-      {
-        return false;
-      }
-
-      m = requestScopeMap.get(scopeId);
-      if (m == null)
-      {
-        return false;
-      }
+      return false;
     }
     
     Set<Map.Entry<String, Object>> s = m.entrySet();
@@ -2282,6 +2353,22 @@ public class BridgeImpl
   // notify this scope's attributes that they are being removed
   private void notifyPreDestroy(Map<String, Object> scope)
   {
+    // Scopes can now contain a Map to child scopes -- first check to see if this scope 
+    // contains such a Map -- if so them remove these scopes too.
+    Map<String, String> childMap = (Map<String, String>) scope.get(CHILD_RESOURCE_REQUEST_SCOPE_MAP);
+    if (childMap != null)
+    {
+      Set<Map.Entry<String, String>> s = childMap.entrySet();
+      Iterator<Map.Entry<String, String>> i = s.iterator();
+  
+      while (i.hasNext())
+      {
+        // the value of each entry is the scope to remove
+        removeRequestScopes(i.next().getValue());
+      }
+    }
+    
+    // Now do the notify
     Set<Map.Entry<String, Object>> s = scope.entrySet();
     Iterator<Map.Entry<String, Object>> i = s.iterator();
     while (i.hasNext())
@@ -2334,13 +2421,26 @@ public class BridgeImpl
 
       if (requestScopeMap != null)
       {
+        Vector<String> scopesToRemove = (Vector<String>) new Vector(5);
+
         Iterator<String> iterator = requestScopeMap.keySet().iterator();
         while (iterator.hasNext())
         {
           String scopeId = iterator.next();
           if (scopeId != null && scopeId.startsWith(scopePrefix))
           {
-            iterator.remove();
+            // don't remove from iterator -- rather directly from the Map
+            // So the Maps.remove is called which invoked notifyPredestroy()
+            scopesToRemove.add(scopeId);
+          }
+        }
+        iterator = scopesToRemove.iterator();
+        while (iterator.hasNext())
+        {
+          String scopeId = iterator.next();
+          if (scopeId != null)
+          {
+            requestScopeMap.remove(scopeId);
           }
         }
       }
@@ -2515,12 +2615,9 @@ public class BridgeImpl
 
     public Map<String, Object> put(String key, Map<String, Object> value)
     {
-      Map<String, Object> o = super.put(key, value);
-      // notify attributes maintained in this object (map) they are going away
-      // Method in the outer BridgeImpl class
-      if (o != null)
-        notifyPreDestroy(o);
-      return o;
+      // Don't notify PreDestroy here.  New entry should be a duplicate/replacement for old
entry
+      // containing the same elements (minus any added/removed in this request)
+      return super.put(key, value);
     }
 
   }

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=982807&r1=982806&r2=982807&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 Aug  5 22:22:10 2010
@@ -105,7 +105,6 @@ public class PortletExternalContextImpl
 
   // Render parameter to store the viewId
   public static final String JSF_TARGET_VIEWID_RENDER_PARAMETER = "__jpfbJSFTARGET";
-  public static final String JSF_RESOURCE_TARGET_VIEWID_RENDER_PARAMETER = "__jpfbJSF_RESTARGET";
   public static final String NO_SCOPE = "org.apache.myfaces.portlet.faces.noScope";
   
   public static final String SERVLET_INCLUDED_PATHINFO_ATTRIBUTE = "javax.servlet.include.path_info";
@@ -883,7 +882,7 @@ public class PortletExternalContextImpl
     {
       // This is a Faces resource
       // put the viewId in the QueryStr.
-      queryStr.addParameter(JSF_RESOURCE_TARGET_VIEWID_RENDER_PARAMETER, viewId);
+      queryStr.addParameter(JSF_TARGET_VIEWID_RENDER_PARAMETER, viewId);
       queryStr.removeParameter(Bridge.PORTLET_MODE_PARAMETER);
       queryStr.removeParameter(Bridge.PORTLET_WINDOWSTATE_PARAMETER);
     }
@@ -1579,17 +1578,11 @@ public class PortletExternalContextImpl
     // Normal case is its returned in the render parameter
     if (viewId == null)
     {
-      // Next Possibility is its a Resource Request
-      viewId = mPortletRequest.getParameter(JSF_RESOURCE_TARGET_VIEWID_RENDER_PARAMETER);
-      
-      if (viewId == null)
-      {
-        // Read the target from the request parameter
+     // Read the target from the request parameter
         
-        viewId = mPortletRequest.getParameter(JSF_TARGET_VIEWID_RENDER_PARAMETER);
-      }
+      viewId = mPortletRequest.getParameter(JSF_TARGET_VIEWID_RENDER_PARAMETER);
 
-      log("PortletExternalContextImpl.getViewId: found jsf target viewId = " + viewId);
+      if (viewId != null) log("PortletExternalContextImpl.getViewId: found jsf target viewId
= " + viewId);
 
       // ViewIds stored in RenderParams are encoded with the Mode to which they apply
       // Ensure current request Mode matches before using the viewId portion

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.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/QueryString.java?rev=982807&r1=982806&r2=982807&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java
(original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/util/QueryString.java
Thu Aug  5 22:22:10 2010
@@ -168,7 +168,7 @@ public final class QueryString
   
   public int numParameters()
   {
-    return mParameterMap.size();
+    return (mParameterMap != null) ? mParameterMap.size() : 0;
   }
 
   public String getParameter(String name)



Mime
View raw message