You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by so...@apache.org on 2007/11/21 23:48:44 UTC

svn commit: r597239 - in /myfaces/portlet-bridge/trunk: 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/org/apache/my...

Author: sobryan
Date: Wed Nov 21 14:48:41 2007
New Revision: 597239

URL: http://svn.apache.org/viewvc?rev=597239&view=rev
Log:
PORTLETBRIDGE-2:  PortletViewHandlerImpl.renderView() fails if included 
                  entity acquires response OutputStream
PORTLETBRIDGE-3:  Bad init param causes infinite loop
PORTLETBRIDGE-14: Setting the request character encoding during a 
                  RenderRequest

Thanks to Michael Freedman for all three patches....

Modified:
    myfaces/portlet-bridge/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
    myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletStateManagerImpl.java
    myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java
    myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
    myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/FacesContextFactoryImpl.java
    myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java

Modified: myfaces/portlet-bridge/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java?rev=597239&r1=597238&r2=597239&view=diff
==============================================================================
--- myfaces/portlet-bridge/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java (original)
+++ myfaces/portlet-bridge/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java Wed Nov 21 14:48:41 2007
@@ -153,7 +153,11 @@
     }
     else
     {
-      doDispatchInternal(request, response, request.getPortletMode());
+      // Bridge didn't process this one -- so forge ahead
+      if (!doDispatchInternal(request, response))
+      {
+        super.doDispatch(request, response);
+      }
     }
   }
 
@@ -161,7 +165,7 @@
   protected void doEdit(RenderRequest request, RenderResponse response) throws PortletException,
                                                                        java.io.IOException
   {
-    doDispatchInternal(request, response, request.getPortletMode());
+    doDispatchInternal(request, response);
 
   }
 
@@ -169,7 +173,7 @@
   protected void doHelp(RenderRequest request, RenderResponse response) throws PortletException,
                                                                        java.io.IOException
   {
-    doDispatchInternal(request, response, request.getPortletMode());
+    doDispatchInternal(request, response);
 
   }
 
@@ -177,7 +181,7 @@
   protected void doView(RenderRequest request, RenderResponse response) throws PortletException,
                                                                        java.io.IOException
   {
-    doDispatchInternal(request, response, request.getPortletMode());
+    doDispatchInternal(request, response);
 
   }
 
@@ -226,24 +230,23 @@
     return getPortletConfig().getInitParameter(Bridge.DEFAULT_VIEWID + "." + mode.toString());
   }
 
-  private void doDispatchInternal(RenderRequest request, RenderResponse response, PortletMode mode)
-                                                                                                   throws PortletException,
-                                                                                                   IOException
+  private boolean doDispatchInternal(RenderRequest request, RenderResponse response)
+     throws PortletException, IOException
   {
-    // Only process if there is a default page defined for this mode
-    String modeDefaultViewId = getDefaultViewId(request, mode);
-
-    if (!(modeDefaultViewId == null))
+    String modeDefaultViewId = getDefaultViewId(request, request.getPortletMode());
+    
+    if (modeDefaultViewId != null)
     {
       WindowState state = request.getWindowState();
       if (!state.equals(WindowState.MINIMIZED))
       {
         doBridgeDispatch(request, response, modeDefaultViewId);
       }
+      return true;
     }
     else
     {
-      super.doDispatch(request, response);
+      return false;
     }
   }
 

Modified: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletStateManagerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletStateManagerImpl.java?rev=597239&r1=597238&r2=597239&view=diff
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletStateManagerImpl.java (original)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletStateManagerImpl.java Wed Nov 21 14:48:41 2007
@@ -31,6 +31,8 @@
 
 import javax.faces.render.ResponseStateManager;
 
+import javax.portlet.faces.BridgeUtil;
+
 import org.apache.myfaces.portlet.faces.bridge.BridgeImpl;
 
 public class PortletStateManagerImpl
@@ -69,13 +71,20 @@
   public void writeState(FacesContext context, Object state)
     throws IOException
   {
+    // Do nothing when not running in portlet request
+    if (!BridgeUtil.isPortletRequest())
+    {
+      super.writeState(context, state);
+      return;
+    }
+
     // Replace current response writer so can grab what is written
     ResponseWriter oldRW = context.getResponseWriter();
     StringWriter stringWriter = new StringWriter(128);
     ResponseWriter newRW = oldRW.cloneWithWriter(stringWriter);
     context.setResponseWriter(newRW);
     
-    mDelegatee.writeState(context, state);
+    super.writeState(context, state);
     
     // Restore real responsewriter
     context.setResponseWriter(oldRW);

Modified: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java?rev=597239&r1=597238&r2=597239&view=diff
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java (original)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java Wed Nov 21 14:48:41 2007
@@ -19,9 +19,12 @@
 
 package org.apache.myfaces.portlet.faces.application;
 
+import java.io.BufferedWriter;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
 import java.io.Writer;
-
+import java.util.Locale;
+import java.util.Map;
 import javax.faces.FacesException;
 import javax.faces.FactoryFinder;
 import javax.faces.application.StateManager;
@@ -37,7 +40,6 @@
 import javax.portlet.faces.Bridge;
 import javax.portlet.faces.BridgeUtil;
 import javax.portlet.faces.component.PortletNamingContainerUIViewRoot;
-
 import org.apache.myfaces.portlet.faces.context.PortletExternalContextImpl;
 
 /**
@@ -71,9 +73,14 @@
   @Override
   public UIViewRoot createView(FacesContext facesContext, String viewId)
   {
+    // Do nothing when not running in portlet request
+    if (!BridgeUtil.isPortletRequest())
+    {
+      return super.createView(facesContext, viewId);
+    }
+
+    UIViewRoot viewRoot = super.createView(facesContext, viewId);
 
-    UIViewRoot viewRoot = mDelegate.createView(facesContext, viewId);
- 
     if (viewRoot.getClass() != UIViewRoot.class)
     {
       return viewRoot;
@@ -91,6 +98,13 @@
   public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException,
                                                                        FacesException
   {
+    // Do nothing when not running in portlet request
+    if (!BridgeUtil.isPortletRequest())
+    {
+      super.renderView(context, viewToRender);
+      return;
+    }
+
     // Get the renderPolicy from the requestScope
     Bridge.BridgeRenderPolicy renderPolicy = (Bridge.BridgeRenderPolicy) context
                                                                                 .getExternalContext()
@@ -103,17 +117,16 @@
       renderPolicy = Bridge.BridgeRenderPolicy.valueOf("DEFAULT");
     }
 
-    if (!BridgeUtil.isPortletRequest()
-        || renderPolicy == Bridge.BridgeRenderPolicy.ALWAYS_DELEGATE)
+    if (renderPolicy == Bridge.BridgeRenderPolicy.ALWAYS_DELEGATE)
     {
-      mDelegate.renderView(context, viewToRender);
+      super.renderView(context, viewToRender);
       return;
     }
     else if (renderPolicy == Bridge.BridgeRenderPolicy.DEFAULT)
     {
       try
       {
-        mDelegate.renderView(context, viewToRender);
+        super.renderView(context, viewToRender);
         return;
       }
       catch (Throwable t)
@@ -188,17 +201,31 @@
     // replace markers in the body content and write it to response.
 
     ResponseWriter responseWriter;
+
+    // Dispatch may have output to an OutputStream instead of a Writer
+    Writer renderResponseWriter = null;
+    try {
+      renderResponseWriter = renderResponse.getWriter();
+    } 
+    catch (IllegalStateException ise) {     
+      // got this exception because we've called getOutputStream() previously
+      renderResponseWriter = new BufferedWriter(
+                          new OutputStreamWriter(
+                               renderResponse.getPortletOutputStream(),
+                               renderResponse.getCharacterEncoding()));
+    }
     if (null != oldWriter)
     {
-      responseWriter = oldWriter.cloneWithWriter(renderResponse.getWriter());
+      responseWriter = oldWriter.cloneWithWriter(renderResponseWriter);
     }
     else
     {
-      responseWriter = newWriter.cloneWithWriter(renderResponse.getWriter());
+      responseWriter = newWriter.cloneWithWriter(renderResponseWriter);
     }
     context.setResponseWriter(responseWriter);
 
     strWriter.write(responseWriter);
+    renderResponseWriter.flush();
 
     if (null != oldWriter)
     {

Modified: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java?rev=597239&r1=597238&r2=597239&view=diff
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java (original)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java Wed Nov 21 14:48:41 2007
@@ -758,15 +758,30 @@
       o instanceof PortletPreferences || o instanceof PortalContext || o instanceof FacesContext || 
       o instanceof ExternalContext || o instanceof ServletConfig || o instanceof ServletContext || 
       o instanceof ServletRequest || o instanceof ServletResponse || o instanceof HttpSession || 
-      s.startsWith("javax.servlet.include") ||
-      s.startsWith("javax.portlet.faces.") ||
-      s.startsWith("org.apache.myfaces.trinidad") ||
-      s.startsWith("com.sun.faces.") ||
-      s.startsWith("javax.portlet.");
+      isInNamespace(s, "javax.portlet.") ||
+      isInNamespace(s, "javax.portlet.faces.") ||
+      isInNamespace(s, "javax.faces.") ||
+      isInNamespace(s, "javax.servlet.") ||
+      isInNamespace(s, "javax.servlet.include.") ||
+      // TODO: remove once support configuring these
+      s.startsWith("org.apache.myfaces.trinidad.") ||
+      s.startsWith("com.sun.faces.");
+    }
+      
+  private boolean isInNamespace(String s, String namespace)
+  {
+    // This is a non-recursive check so s must be the result of removing the namespace.
+    if (s.startsWith(namespace))
+    {
+    // extract entire namespace and compare
+    s = s.substring(0, s.lastIndexOf('.') + 1);
+    return s.equals(namespace);
+    }
+    return false;
   }
 
-	@SuppressWarnings("unchecked")
-	private boolean restoreBridgeRequestScopeData(FacesContext context, String scopeId)
+  @SuppressWarnings("unchecked")
+  private boolean restoreBridgeRequestScopeData(FacesContext context, String scopeId)
     throws BridgeException
   {
 

Modified: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/FacesContextFactoryImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/FacesContextFactoryImpl.java?rev=597239&r1=597238&r2=597239&view=diff
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/FacesContextFactoryImpl.java (original)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/FacesContextFactoryImpl.java Wed Nov 21 14:48:41 2007
@@ -26,6 +26,9 @@
 import javax.portlet.PortletConfig;
 import javax.portlet.PortletRequest;
 import javax.portlet.PortletResponse;
+import javax.portlet.faces.Bridge;
+import javax.portlet.faces.BridgeUtil;
+import javax.servlet.ServletRequest;
 
 /**
  * A factory object that creates (if needed) and returns new FacesContext instance for running in
@@ -46,16 +49,26 @@
   public FacesContext getFacesContext(Object config, Object request, Object response,
                                       Lifecycle lifecycle) throws FacesException
   {
-    // if in portlet environment
-    if (config instanceof PortletConfig && request instanceof PortletRequest
-        && response instanceof PortletResponse)
+    // if in portlet environment -- do a portlet container neutral test
+    // first in case we are packaged in a web app that isn't deployed 
+    // on a portlet container/as a portlet. Note:  can't use the BridgeUtil
+    // method as that call requires the facesContext to exist.
+    if (isPortletRequest(request))
     {
-
-      return new PortletFacesContextImpl(
+      // make sure they passed the right objects
+      if (config instanceof PortletConfig && request instanceof PortletRequest
+        && response instanceof PortletResponse)
+      {
+        return new PortletFacesContextImpl(
                                          new PortletExternalContextImpl((PortletConfig) config,
                                                                         (PortletRequest) request,
                                                                         (PortletResponse) response),
                                          lifecycle);
+      }
+      else
+      {
+        throw new FacesException("getFacesContext failed: Running in a portlet request butnot passed portlet objects");
+      }
     }
     else
     {
@@ -63,4 +76,26 @@
       return mHandler.getFacesContext(config, request, response, lifecycle);
     }
   }
+  
+  
+  private boolean isPortletRequest(Object request) 
+  {
+    // could be either a servlet or portlet request object (or both)
+    // Check servlet side first in case we are packaged in an application
+    // that is running as a servlet in an environment that doesn't contain
+    // a portlet container.
+    if (request instanceof ServletRequest)
+    {
+      ServletRequest sr = (ServletRequest) request;
+      Bridge.PortletPhase phase = (Bridge.PortletPhase) sr.getAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
+      return (phase != null);
+    }
+    else if (request instanceof PortletRequest)
+    {
+      return true;
+    }
+      
+    return false;
+  }
+  
 }

Modified: myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java?rev=597239&r1=597238&r2=597239&view=diff
==============================================================================
--- myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java (original)
+++ myfaces/portlet-bridge/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java Wed Nov 21 14:48:41 2007
@@ -775,13 +775,22 @@
   public void setRequestCharacterEncoding(String encoding) throws UnsupportedEncodingException,
                                                           IllegalStateException
   {
-    if (mPhase != Bridge.PortletPhase.ActionPhase)
+    /* TODO: Temporary workaround for JIRA PORTLETBRIDGE-14 until EG
+     * decides on best course of action.
+     * 
+   if (mPhase != Bridge.PortletPhase.ActionPhase)
     {
-      throw new IllegalStateException(
-                                      "PortletExternalContextImpl.setRequestCharacterEncoding(): Request must be an ActionRequest");
+          
+        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.ActionPhase)
+    {
+      ((ActionRequest) mPortletRequest).setCharacterEncoding(encoding);
     }
-
-    ((ActionRequest) mPortletRequest).setCharacterEncoding(encoding);
   }
 
   /**