You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mf...@apache.org on 2008/07/25 01:01:57 UTC

svn commit: r679608 - in /myfaces/portlet-bridge/core/trunk: api/src/main/java/javax/portlet/faces/ impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/ impl/src/main/java/org/apache/myfaces/portlet/faces/context/

Author: mfreedman
Date: Thu Jul 24 16:01:57 2008
New Revision: 679608

URL: http://svn.apache.org/viewvc?rev=679608&view=rev
Log:
PORTLETBRIDGE-44 : Implement Revision 15 support for nonFaces targets

Bridge recognizes nonFaces targets in encodeActionURL and encodes in a public parameter.  GenericFacesPortlet recognizes this parameter and dispatches to the path based nonFaces target.  Similar mechanism is used to get back to a Faces target from a nonFaces target.

Added:
    myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeInvalidViewPathException.java
    myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeNotAFacesRequestException.java
Modified:
    myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/Bridge.java
    myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
    myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
    myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java

Modified: myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/Bridge.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/Bridge.java?rev=679608&r1=679607&r2=679608&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/Bridge.java (original)
+++ myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/Bridge.java Thu Jul 24 16:01:57 2008
@@ -42,12 +42,14 @@
  * Implementations of this <code>Bridge</code> interface are required to have a <code>code</code>
  * constructor.
  */
+public interface
 
-public interface Bridge
+Bridge
 {
 
   // Base Bridge attribute/context parameter prefix
-  public static final String BRIDGE_PACKAGE_PREFIX         = "javax.portlet.faces.";
+  public static final String BRIDGE_PACKAGE_PREFIX = 
+    "javax.portlet.faces.";
 
   // Following are the names of context init parameters that control
   // Bridge behavior. These are specified in the web.xml
@@ -56,51 +58,113 @@
    * Context initialization parameter that specifies the maximum number of bridge
    * request scopes to preserved across all uses within this application.
    */
-  public static final String MAX_MANAGED_REQUEST_SCOPES    = BRIDGE_PACKAGE_PREFIX
-                                                             + "MAX_MANAGED_REQUEST_SCOPES";
-  
+  public static final String MAX_MANAGED_REQUEST_SCOPES = BRIDGE_PACKAGE_PREFIX + "MAX_MANAGED_REQUEST_SCOPES";
+
   /**
    * Context initialization parameter that defines the policy the bridge uses for
    * rendering.  Parameter value is the string representaiton of one of the 
    * BridgeRenderPolicy enum values.
-   */  
-  public static final String RENDER_POLICY                 = BRIDGE_PACKAGE_PREFIX
-                                                              + "RENDER_POLICY";
+   */
+  public static final String RENDER_POLICY = BRIDGE_PACKAGE_PREFIX + "RENDER_POLICY";
+
   /**
    * Context initialization parameter that defines the lifecycle ID used to 
    * identify the Faces Lifecycle used for this application.
-   */ 
-  public static final String LIFECYCLE_ID                  = "javax.faces.LIFECYCLE_ID";
+   */
+  public static final String LIFECYCLE_ID = "javax.faces.LIFECYCLE_ID";
 
   /**
    * Context initialization parameter that defines the SAVESTATE_FIELD_MARKER
-   * in use in the given deployment.  If not set, the Bridge will detect and run
-   * properly in either the Faces RI or MyFaces environments.
-   */ 
-  public static final String SAVESTATE_FIELD_MARKER          = BRIDGE_PACKAGE_PREFIX
-                                                              + "SAVESTATE_FIELD_MARKER";
+   * in use in the given deployment.  If not set, consult your bridge implementation
+   * documentation to determine which Faces implementations it automatically
+   * detects and supports.  For example the bridge RI will detect and run
+   * properly in either the Faces RI or MyFaces environments without this being set.
+   */
+  public static final String SAVESTATE_FIELD_MARKER = BRIDGE_PACKAGE_PREFIX + "SAVESTATE_FIELD_MARKER";
+
+  // Following are the names of context init attributes set by the portlet to control
+  // Bridge behavior. For the GenericFacesPortlet, the values for these come from 
+  // portlet initialization parameters in the portlet.xml
+  
+  /** A PortletContext attribute that a portlet can set prior
+   * to calling the bridge's init() method to configure the bridge to preserve
+   * action parameters received by this portlet along with bridge's request scope so
+   * that they may be restored and acessed in subsequent renders.  If "true", the
+   * action parameters are preserved.  If "false", they are not preserved.  The bridge
+   * default is "false".<br>
+   *
+   * As this attribute is scoped to a specific portlet in an application-wide context
+   * the attribute name must be include the portlet name as follows:
+   * BRIDGE_PACKAGE_PREFIX + context.getPortletName() + preserveActionParams
+   */
+  public static final String PRESERVE_ACTION_PARAMS = "preserveActionParams";
 
-  /**
-   * Bridge attribute that signals this request is a Faces postback.  Its provided as
-   * an alternative signal to the common reliance on the view state parameter as
-   * an indicator that this is a postback request.  Implementations needing this 
-   * information and not using the view state parameter indicator can check this 
-   * attribute when running in a portlet environment.
-   */ 
-  // Attribute signifying whether this render is a postback or not.
-  public static final String IS_POSTBACK_ATTRIBUTE         = BRIDGE_PACKAGE_PREFIX + "isPostback";
+
+  /** A PortletContext attribute that a portlet can set prior
+   * to calling the bridge's init() method to configure the bridge to exclude
+   * specific attributes from its bridge request scope. Value is a comma delimited
+   * list containing either a fully qualified attribute name or package name terminated
+   * with a ".*" wildcard indicator.  In this later case, all attributes in the package
+   * name which precedes the ".*" are excluded, non recursive.<br>
+   *
+   * As this attribute is scoped to a specific portlet in an application-wide context
+   * the attribute name must be include the portlet name as follows:
+   * BRIDGE_PACKAGE_PREFIX + context.getPortletName() + excludedRequestAttributes
+   */
+  public static final String EXCLUDED_REQUEST_ATTRIBUTES = "excludedRequestAttributes";
+
+  /** PortletContext attribute that a portlet must set prior
+   * to calling the bridge's init() method to convey to the bridge the set of default
+   * viewIds that correspond to this portlet's supported <code>PortletMode</code>s. 
+   * Its value is a Map with one entry per mode.  The mode name is the key.  The entry's
+   * value is the corresponding default viewId the bridge should use for this mode.
+   * <br>
+   *
+   * As this attribute is scoped to a specific portlet in an application-wide context
+   * the attribute name must be include the portlet name as follows:
+   * BRIDGE_PACKAGE_PREFIX + context.getPortletName() + DEFAULT_VIEWID_MAP
+   */
+  public static final String DEFAULT_VIEWID_MAP = "defaultViewIdMap";
+  
+  // The following are request attributes a portlet can set to control the request
+  // processing of the bridge.  
+  
+  /** PortletRequest attribute that a portlet may set prior
+   * to calling the bridge's doFacesRequest() method.  The value of this
+   * attribute is a <code>String</code> representing the Faces viewId the
+   * bridge is to target for this request.  Used by a portlet to specifically 
+   * control a request's view target in situations such as navigating from
+   * a nonFaces view to a specific Faces view (other than the default).<p>
+   * Generally, the use of this attribute is mutually exclusive with the use
+   * of VIEW_PATH.  If both have been set in a given request, the bridge gives
+   * precedence to VIEW_ID.
+   */
+  public static final String VIEW_ID = BRIDGE_PACKAGE_PREFIX + "viewId";
+  
+  /** PortletRequest attribute that a portlet may set prior
+   * to calling the bridge's doFacesRequest() method.  The value of this
+   * attribute is a <code>String</code> containing a <code>ContextPath</code>
+   * relative path in which the Faces viewId is encoded.  Like VIEW_ID, this
+   * attribute provides a means for a portlet to explicitly control the Faces
+   * target for a specific request.  It is used in situations such as navigating from
+   * a nonFaces view to a specific Faces view (other than the default).<p>
+   * Generally, the use of this attribute is mutually exclusive with the use
+   * of VIEW_PATH.  If both have been set in a given request, the bridge gives
+   * precedence to VIEW_ID.
+   */
+  public static final String VIEW_PATH = BRIDGE_PACKAGE_PREFIX + "viewPath";
 
   // Names for special QueryString parameters names the Bridge recognizes in
   // encodeActionURL as signifying to change the corresponding portlet values
   // in the resulting URL
-  
+
   /**
    * Special token parameter in the url passed to the bridge's ExternalContext.encodeActionURL()
    * that it recognizes as an indication that this action should encode a PortletMode
    * change to the one indicated by the parameter's value.
    */
   public static final String PORTLET_MODE_PARAMETER = BRIDGE_PACKAGE_PREFIX + "PortletMode";
-  
+
   /**
    * Special token parameter in the url passed to the bridge's ExternalContext.encodeActionURL()
    * that it recognizes as an indication that this action should encode a WindowState change to
@@ -121,7 +185,7 @@
    * and hence shouldn't be encoded as a Portlet action.  Rather encodeActionURL merely returns
    * this url unchanged.
    */
-  public static final String DIRECT_LINK                   = BRIDGE_PACKAGE_PREFIX + "DirectLink";
+  public static final String DIRECT_LINK = BRIDGE_PACKAGE_PREFIX + "DirectLink";
 
   /**
    * Special token parameter in the url passed to the bridge's ExternalContext.encodeResourceURL()
@@ -129,9 +193,8 @@
    * contains this portlet should be encoded in the resource url. This reference is
    * encoded as the value of a query string parameter whose name is the value of this back
    * link token parameter.
-   */  
-
-  public static final String BACK_LINK                     = BRIDGE_PACKAGE_PREFIX + "BackLink";
+   */
+  public static final String BACK_LINK = BRIDGE_PACKAGE_PREFIX + "BackLink";
 
   /**
    * Special token parameter in the url passed to the bridge's ExternalContext.encodeResourceURL()
@@ -139,50 +202,22 @@
    * hence should be encoded as an portlet ActionURL rather then a portlet resource url.  This token
    * is intended for use in urls signifying a view navigation using components such as
    * <code>h:outputLink</code>. 
-   */  
-
-  public static final String VIEW_LINK                     = BRIDGE_PACKAGE_PREFIX + "ViewLink";
-   
-  /** A PortletContext attribute that a portlet can set prior
-   * to calling the bridge's init() method to configure the bridge to preserve
-   * action parameters received by this portlet along with bridge's request scope so
-   * that they may be restored and acessed in subsequent renders.  If "true", the
-   * action parameters are preserved.  If "false", they are not preserved.  The bridge
-   * default is "false".<br>
-   *
-   * As this attribute is scoped to a specific portlet in an application-wide context
-   * the attribute name must be include the portlet name as follows:
-   * BRIDGE_PACKAGE_PREFIX + context.getPortletName() + preserveActionParams
    */
-  public static final String PRESERVE_ACTION_PARAMS        = "preserveActionParams";
+  public static final String VIEW_LINK = BRIDGE_PACKAGE_PREFIX + "ViewLink";
 
 
-  /** A PortletContext attribute that a portlet can set prior
-   * to calling the bridge's init() method to configure the bridge to exclude
-   * specific attributes from its bridge request scope. Value is a comma delimited
-   * list containing either a fully qualified attribute name or package name terminated
-   * with a ".*" wildcard indicator.  In this later case, all attributes in the package
-   * name which precedes the ".*" are excluded, non recursive.<br>
-   *
-   * As this attribute is scoped to a specific portlet in an application-wide context
-   * the attribute name must be include the portlet name as follows:
-   * BRIDGE_PACKAGE_PREFIX + context.getPortletName() + excludedRequestAttributes
-   */
-  public static final String EXCLUDED_REQUEST_ATTRIBUTES    = "excludedRequestAttributes";
+  // Request attributes set by the bridge that can be used by Faces extensions
+  // and/or applications to properly run in a portlet environment. 
 
-  /** PortletContext attribute that a portlet must set prior
-   * to calling the bridge's init() method to convey to the bridge the set of default
-   * viewIds that correspond to this portlet's supported <code>PortletMode</code>s. 
-   * Its value is a Map with one entry per mode.  The mode name is the key.  The entry's
-   * value is the corresponding default viewId the bridge should use for this mode.
-   * <br>
-   *
-   * As this attribute is scoped to a specific portlet in an application-wide context
-   * the attribute name must be include the portlet name as follows:
-   * BRIDGE_PACKAGE_PREFIX + context.getPortletName() + DEFAULT_VIEWID_MAP
+  /**
+   * A PortletRequest attribute set by the bridge when processing a Faces request
+   * that signals this request is a Faces postback.  Its provided as
+   * an alternative signal to the common reliance on the view state parameter as
+   * an indicator that this is a postback request.  Implementations needing this 
+   * information and not using the view state parameter indicator can check this 
+   * attribute when running in a portlet environment.
    */
-  public static final String DEFAULT_VIEWID_MAP                = "defaultViewIdMap";
-
+  public static final String IS_POSTBACK_ATTRIBUTE = BRIDGE_PACKAGE_PREFIX + "isPostback";
 
   /** A PortletRequest attribute set by the bridge in its
    * <code>ViewHandler.renderView</code> prior to dispatching the request
@@ -191,16 +226,23 @@
    * rendering the view components.  In conjunction with the filter this enables
    * preserving rendering order of native JSP rendering and Faces rendering in a jsp.
    */
-  public static final String RENDER_CONTENT_AFTER_VIEW     = BRIDGE_PACKAGE_PREFIX
-                                                             + "RenderContentAfterView";
+  public static final String RENDER_CONTENT_AFTER_VIEW = BRIDGE_PACKAGE_PREFIX + "RenderContentAfterView";
+
   /** A PortletRequest attribute set by an include filter in recognition of the
    * RenderContentAfterView bridge attribute.  Its value is either char[] or byte[]
    * holding the AFTER_VIEW_CONTENT generated while rendering this jsp.
    * In conjunction with the bridge this enables
    * preserving rendering order of native JSP rendering and Faces rendering in a jsp.
    */
-  public static final String AFTER_VIEW_CONTENT            = BRIDGE_PACKAGE_PREFIX
-                                                             + "AfterViewContent";
+  public static final String AFTER_VIEW_CONTENT = BRIDGE_PACKAGE_PREFIX + "AfterViewContent";
+
+  /** PortletRequest attribute set by the bridge prior to creating/acquiring a
+   * <code>FacesContext</code>.  Its value indicates which portlet phase this 
+   * Faces is executing in.  It can be used by Faces subsystems not only to determine
+   * the portlet exectution phase but if present (not null) as an indication the request
+   * is being processed in a portlet container.
+   */
+  public static final String PORTLET_LIFECYCLE_PHASE = BRIDGE_PACKAGE_PREFIX + "phase";
 
   /** PortletSession attribute set by the bridge to hold the last viewId accessed in a given mode.  
    * The attribute (key) is composed of this name + the mode name.  I.e. 
@@ -210,30 +252,60 @@
    * for the mode.  Attribute is used by developers to reference/return to the last view in
    * a given Mode from another mode.
    */
-  public static final String VIEWID_HISTORY       = BRIDGE_PACKAGE_PREFIX + "viewIdHistory";
+  public static final String VIEWID_HISTORY = BRIDGE_PACKAGE_PREFIX + "viewIdHistory";
 
 
-  /** PortletRequest attribute set by the bridge prior to creating/acquiring a
-   * <code>FacesContext</code>.  Its value indicates which portlet phase this 
-   * Faces is executing in.  It can be used by Faces subsystems not only to determine
-   * the portlet exectution phase but if present (not null) as an indication the request
-   * is being processed in a portlet container.
-   */
-  public static final String PORTLET_LIFECYCLE_PHASE       = BRIDGE_PACKAGE_PREFIX + "phase";
-
   /** Name of PortletResponse property set by the bridge when it recognizes that the 
    * view has been rendered using a <code>NamingContainer</code> that ensures all
    * generated ids are namespaced using the consumer provided unique portlet id.
    */
   public static final String PORTLET_NAMESPACED_RESPONSE_PROPERTY = "X-JAVAX-PORTLET-NAMESPACED-RESPONSE";
+  
+  /** Name of the render parameter set by the bridge when it encodes a navigation
+   *  link to a nonFaces target. Though the bridge recognizes nonFaces targets when
+   *  it encodes a navigational link, it does not handle the subsequent request. 
+   *  It only handles requests for Faces targets.  It is the portlet's responsibility
+   *  to detect and handle these requests.  When the nonFaces target is a path based
+   *  resource (such as a jsp or servlet), the <code>ContextPath</code> relative path
+   *  of the resource is written as the value of this render parameter.  For convenience,
+   *  the GenericFacesPortlet recognizes this render parameter in received requests
+   *  and uses the <code>PortletRequestDispatcher</code> to dispatch to the encoded
+   *  path instead of calling the bridge to execute the request.
+   */
+  public static final String NONFACES_TARGET_PATH_PARAMETER = "_jsfBridgeNonFacesView";
+  
+  /** Name of a request parameter (generally) encoded in a link from a nonFaces
+   *  view response.  It acts as a marker to the portlet that the nonFaces view
+   *  intends to navigate to the Faces view expressed in the value of this parameter.
+   *  It differs from the <code>FACES_VIEW_PATH_PARAMETER</code> in that its value
+   *  is the actual Faces viewId of the target while the formaer is a
+   *  <code>ContextPath</code> relative path containing the viewId.<p>
+   *  Portlets receiving such a parameter should set the the corresponding request
+   *  attribute <code>javax.portlet.faces.viewId</code> before calling the bridge
+   *  to handle the request.
+   */
+  public static final String FACES_VIEW_ID_PARAMETER = "_jsfBridgeViewId";
+  
+  /** Name of a request parameter (generally) encoded in a link from a nonFaces
+   *  view response.  It acts as a marker to the portlet that the nonFaces view
+   *  intends to navigate to the Faces view expressed in the value of this parameter.
+   *  It differs from the <code>FACES_VIEW_ID_PARAMETER</code> in that its value
+   *  is a <code>ContextPath</code> relative path containing the viewId while the former
+   *  is the viewId itself.<p>
+   *  Portlets receiving such a parameter should set the the corresponding request
+   *  attribute <code>javax.portlet.faces.viewPath</code> before calling the bridge
+   *  to handle the request.
+   */
+  public static final String FACES_VIEW_PATH_PARAMETER = "_jsfBridgeViewPath";
 
   /** Enumeration whose values describe the current portlet phase the bridge
    * is executing Faces within.
    */
-
   public static enum PortletPhase
   {
-    ACTION_PHASE, RENDER_PHASE;
+    ACTION_PHASE,
+    RENDER_PHASE,
+    ;
   }
 
   /** Enumeration whose values describe the render policy used by the bridge
@@ -246,7 +318,10 @@
    */
   public static enum BridgeRenderPolicy
   {
-    DEFAULT, ALWAYS_DELEGATE, NEVER_DELEGATE;
+    DEFAULT,
+    ALWAYS_DELEGATE,
+    NEVER_DELEGATE,
+    ;
   }
 
   /**
@@ -314,10 +389,10 @@
    * @throws BridgeException
    *           all other internal exceptions are converted to a BridgeException.
    */
-  public void doFacesRequest(ActionRequest request, ActionResponse response)
-       throws BridgeDefaultViewNotSpecifiedException,
-              BridgeUninitializedException,
-              BridgeException;
+  public void doFacesRequest(ActionRequest request, 
+                             ActionResponse response)
+    throws BridgeDefaultViewNotSpecifiedException, 
+           BridgeUninitializedException, BridgeException;
 
   /**
    * Called by the portlet when it wants the bridge to process a render request.
@@ -334,10 +409,10 @@
    * @throws BridgeException
    *           all other internal exceptions are converted to a BridgeException.
    */
-  public void doFacesRequest(RenderRequest request, RenderResponse response)
-       throws BridgeDefaultViewNotSpecifiedException,
-              BridgeUninitializedException,
-              BridgeException;
+  public void doFacesRequest(RenderRequest request, 
+                             RenderResponse response)
+    throws BridgeDefaultViewNotSpecifiedException, 
+           BridgeUninitializedException, BridgeException;
 
   /**
    * Called by the portlet to take the bridge out of service. Once out of service, the bridge must

Added: myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeInvalidViewPathException.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeInvalidViewPathException.java?rev=679608&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeInvalidViewPathException.java (added)
+++ myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeInvalidViewPathException.java Thu Jul 24 16:01:57 2008
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
+ * law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
+ * for the specific language governing permissions and limitations under the License.
+ */
+package javax.portlet.faces;
+
+/**
+ * Thrown when the bridge can't resolve the target view from the ViewPath
+ * PortletRequest attribute <code>javax.portlet.faces.viewPath</code>.
+ */
+public class BridgeInvalidViewPathException extends BridgeException
+{
+
+  public BridgeInvalidViewPathException()
+  {
+    super();
+  }
+
+  public BridgeInvalidViewPathException(String message)
+  {
+    super(message);
+  }
+
+  public BridgeInvalidViewPathException(String message, Throwable cause)
+  {
+    super(message, cause);
+  }
+
+  public BridgeInvalidViewPathException(Throwable cause)
+  {
+    super(cause);
+  }
+}

Added: myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeNotAFacesRequestException.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeNotAFacesRequestException.java?rev=679608&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeNotAFacesRequestException.java (added)
+++ myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/BridgeNotAFacesRequestException.java Thu Jul 24 16:01:57 2008
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
+ * law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
+ * for the specific language governing permissions and limitations under the License.
+ */
+package javax.portlet.faces;
+
+/**
+ * Thrown when the bridge finds that the request is encoded with its marker
+ * indicating its a nonFaces target.
+ */
+public class BridgeNotAFacesRequestException extends BridgeException
+{
+
+  public BridgeNotAFacesRequestException()
+  {
+    super();
+  }
+
+  public BridgeNotAFacesRequestException(String message)
+  {
+    super(message);
+  }
+
+  public BridgeNotAFacesRequestException(String message, Throwable cause)
+  {
+    super(message, cause);
+  }
+
+  public BridgeNotAFacesRequestException(Throwable cause)
+  {
+    super(cause);
+  }
+}

Modified: myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java?rev=679608&r1=679607&r2=679608&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java (original)
+++ myfaces/portlet-bridge/core/trunk/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java Thu Jul 24 16:01:57 2008
@@ -30,6 +30,8 @@
 import javax.portlet.PortletException;
 import javax.portlet.PortletMode;
 import javax.portlet.PortletRequest;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.PortletResponse;
 import javax.portlet.RenderRequest;
 import javax.portlet.RenderResponse;
 import javax.portlet.WindowState;
@@ -208,7 +210,7 @@
     else
     {
       // Bridge didn't process this one -- so forge ahead
-      if (!doDispatchInternal(request, response))
+      if (!doRenderDispatchInternal(request, response))
       {
         super.doDispatch(request, response);
       }
@@ -219,7 +221,7 @@
   protected void doEdit(RenderRequest request, RenderResponse response) throws PortletException,
                                                                        java.io.IOException
   {
-    doDispatchInternal(request, response);
+    doRenderDispatchInternal(request, response);
 
   }
 
@@ -227,7 +229,7 @@
   protected void doHelp(RenderRequest request, RenderResponse response) throws PortletException,
                                                                        java.io.IOException
   {
-    doDispatchInternal(request, response);
+    doRenderDispatchInternal(request, response);
 
   }
 
@@ -235,7 +237,7 @@
   protected void doView(RenderRequest request, RenderResponse response) throws PortletException,
                                                                        java.io.IOException
   {
-    doDispatchInternal(request, response);
+    doRenderDispatchInternal(request, response);
 
   }
 
@@ -244,7 +246,7 @@
                                                                            throws PortletException,
                                                                            IOException
   {
-    doBridgeDispatch(request, response);
+    doActionDispatchInternal(request, response);
   }
 
   /**
@@ -401,13 +403,44 @@
     
     return mDefaultViewIdMap;
   }
+  
+  private boolean isNonFacesRequest(PortletRequest request, PortletResponse response)
+  {
+    // Non Faces request is identified by either the presence of the _jsfBridgeNonFacesView
+    // parameter or the request being for a portlet mode which doesn't have a default
+    // Faces view configured for it.
+    if (request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER) != null)
+    {
+      return true;
+    }
+    
+    String modeDefaultViewId = mDefaultViewIdMap.get(request.getPortletMode().toString());
+    return modeDefaultViewId == null;
+  }
+  
+  private void doActionDispatchInternal(ActionRequest request, ActionResponse response)
+     throws PortletException, IOException
+  {
+    // First determine whether this is a Faces or nonFaces request
+    if (isNonFacesRequest(request, response))
+    {
+      throw new PortletException("GenericFacesPortlet:  Action request is not for a Faces target.  Such nonFaces requests must be handled by a subclass.");
+    }
+    else
+    {
+      doBridgeDispatch(request, response);
+    }
+  }
 
-  private boolean doDispatchInternal(RenderRequest request, RenderResponse response)
+  private boolean doRenderDispatchInternal(RenderRequest request, RenderResponse response)
      throws PortletException, IOException
   {
-    String modeDefaultViewId = mDefaultViewIdMap.get(request.getPortletMode().toString());
-    
-    if (modeDefaultViewId != null)
+    // First determine whether this is a Faces or nonFaces request
+    if (isNonFacesRequest(request, response))
+    {
+      return doNonFacesDispatch(request, response);
+    }
+    else
     {
       WindowState state = request.getWindowState();
       if (!state.equals(WindowState.MINIMIZED))
@@ -416,17 +449,42 @@
       }
       return true;
     }
-    else
+  }
+  
+  private boolean doNonFacesDispatch(RenderRequest request, RenderResponse response)
+    throws PortletException
+  {
+    // Can only dispatch if the path is encoded in the request parameter
+    String targetPath = request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER);
+    if (targetPath == null)
     {
+      // Didn't handle this request
       return false;
     }
+    
+    // merely dispatch this to the nonJSF target
+    // but because this is portlet 1.0 we have to ensure the content type is set.
+    // Ensure the ContentType is set before rendering
+    if (response.getContentType() == null)
+    {
+      response.setContentType(request.getResponseContentType());
+    }
+    try {
+      PortletRequestDispatcher dispatcher = this.getPortletContext().getRequestDispatcher(targetPath);
+      dispatcher.include(request, response);
+      return true;
+    }
+    catch (Exception e)
+    {
+      throw new PortletException("Unable to dispatch to: " + targetPath, e);
+    }
   }
 
   private void doBridgeDispatch(RenderRequest request, RenderResponse response)
-                                                                                                     throws PortletException
+    throws PortletException
   {
     // initial Bridge if not already active
-    initBridge();
+    initBridgeRequest(request, response);
     
     // Set the response ContentType/CharacterSet
     setResponseContentType(
@@ -448,10 +506,10 @@
   }
 
   private void doBridgeDispatch(ActionRequest request, ActionResponse response)
-                                                                                                     throws PortletException
+   throws PortletException
   {
     // initial Bridge if not already active
-    initBridge();
+    initBridgeRequest(request, response);
 
     try
     {
@@ -465,9 +523,35 @@
     }
 
   }
+  
+  private void initBridgeRequest(PortletRequest request, PortletResponse response)
+    throws PortletException
+  {
+    initBridge();
+    
+    
+    // Now do any per request initialization
+    // I nthis case look to see if the request is encoded (usually 
+    // from a NonFaces view response) with the specific Faces
+    // view to execute.
+    String view = request.getParameter(Bridge.FACES_VIEW_ID_PARAMETER);
+    if (view != null)
+    {
+      request.setAttribute(Bridge.VIEW_ID, view);
+    }
+    else
+    {
+      view = request.getParameter(Bridge.FACES_VIEW_PATH_PARAMETER);
+      if (view != null)
+      {
+        request.setAttribute(Bridge.VIEW_PATH, view);
+      }
+    }
+  }
 
   private void initBridge() throws PortletException
   {
+    // Ensure te Bridge has been constrcuted and initialized
     if (mFacesBridge == null)
     {
       try

Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java?rev=679608&r1=679607&r2=679608&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java Thu Jul 24 16:01:57 2008
@@ -73,6 +73,7 @@
 import javax.portlet.faces.Bridge;
 import javax.portlet.faces.BridgeDefaultViewNotSpecifiedException;
 import javax.portlet.faces.BridgeException;
+import javax.portlet.faces.BridgeNotAFacesRequestException;
 import javax.portlet.faces.BridgeUninitializedException;
 import javax.portlet.faces.annotation.BridgePreDestroy;
 import javax.portlet.faces.annotation.BridgeRequestScopeAttributeAdded;
@@ -216,6 +217,13 @@
       throw new BridgeUninitializedException();
     else if (request == null || response == null)
       throw new NullPointerException("request or response parameter is null");
+    
+    // First check to see whether this is a non-JSF request
+    if (request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER) != null)
+    {
+      throw new BridgeNotAFacesRequestException("NonFaces target = "
+            + request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER));
+    }
 
     // must wait until after init to get at the session
     // since view mode mapping must always exist -- check it
@@ -316,7 +324,7 @@
     }
     catch (Exception e)
     {
-      context.getExternalContext().log("Exception thrown in doFacesRequest:action", e);
+      mPortletConfig.getPortletContext().log("Exception thrown in doFacesRequest:action", e);
       if (!(e instanceof BridgeException))
       {
         Throwable rootCause = e.getCause();
@@ -334,17 +342,17 @@
       // its actively working on a request -- remove it to indicate we are done
       request.removeAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
       
-      // remove the redirect attr so its not carried over to the 
-      // render in environments in which action/render are run in the
-      // same request ctx.  There are two potential attrs -- the one on 
-      // the request holds info if a redirect occurred within this request
-      // The one on the session caches the redirect that occurred during render 
-      // so it can be used in subsequent renders that occur before the action.
-      context.getExternalContext().getRequestMap().remove(BridgeImpl.REDIRECT_VIEWPARAMS);
-      context.getExternalContext().getSessionMap().remove(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS);
       
       if (context != null)
       {
+        // remove the redirect attr so its not carried over to the 
+        // render in environments in which action/render are run in the
+        // same request ctx.  There are two potential attrs -- the one on 
+        // the request holds info if a redirect occurred within this request
+        // The one on the session caches the redirect that occurred during render 
+        // so it can be used in subsequent renders that occur before the action.
+        context.getExternalContext().getRequestMap().remove(BridgeImpl.REDIRECT_VIEWPARAMS);
+        context.getExternalContext().getSessionMap().remove(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS);
         context.release();
       }
     }
@@ -399,11 +407,10 @@
       throw new NullPointerException("request or response parameter is null");
     
     // First check to see whether this is a non-JSF render request
-    String nonJSFTarget = request.getParameter(PortletExternalContextImpl.NONJSF_TARGET_RENDER_PARAMETER);
-    if (nonJSFTarget != null)
+    if (request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER) != null)
     {
-      dispatchNonJSFTarget(request, response, nonJSFTarget);
-      return;
+      throw new BridgeNotAFacesRequestException("NonFaces target = "
+            + request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER));
     }
 
     // must wait until after init to get at the session
@@ -532,7 +539,7 @@
         removeRequestScopes(scopeId);
       }
 
-      context.getExternalContext().log("Exception thrown in doFacesRequest:render", e);
+      mPortletConfig.getPortletContext().log("Exception thrown in doFacesRequest:render", e);
       if (!(e instanceof BridgeException))
       {
         Throwable rootCause = e.getCause();
@@ -813,27 +820,7 @@
     }
   }
   
-  private void dispatchNonJSFTarget(RenderRequest request, RenderResponse response, String nonJSFTarget)
-    throws BridgeException
-  {
-    // merely dispatch this to the nonJSF target
-    // but because this is portlet 1.0 we have to ensure the content type is set.
-    // Ensure the ContentType is set before rendering
-    if (response.getContentType() == null)
-    {
-      response.setContentType(request.getResponseContentType());
-    }
-    try {
-      PortletRequestDispatcher dispatcher = mPortletConfig.getPortletContext().getRequestDispatcher(nonJSFTarget);
-      dispatcher.include(request, response);
-    }
-    catch (Exception e)
-    {
-      throw new BridgeException("Unable to dispatch to: " + nonJSFTarget, e);
-    }
-  }
 
-  
   private void initViewHistoryDefaults(PortletSession session, Map<String, String> viewIdDefaultMap)
   {
     Set<String> keys = viewIdDefaultMap.keySet();

Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java?rev=679608&r1=679607&r2=679608&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java Thu Jul 24 16:01:57 2008
@@ -57,6 +57,7 @@
 import javax.portlet.WindowState;
 import javax.portlet.faces.Bridge;
 import javax.portlet.faces.BridgeDefaultViewNotSpecifiedException;
+import javax.portlet.faces.BridgeInvalidViewPathException;
 import javax.portlet.faces.BridgeUtil;
 
 import org.apache.myfaces.portlet.faces.bridge.BridgeImpl;
@@ -92,7 +93,6 @@
 
   // Render parameter to store the viewId
   public static final String JSF_TARGET_VIEWID_RENDER_PARAMETER = "__jpfbJSFTARGET";
-  public static final String NONJSF_TARGET_RENDER_PARAMETER = "__jpfbNonJSFTARGET";
   public static final String NO_SCOPE = "org.apache.myfaces.portlet.faces.noScope";
   
 
@@ -131,8 +131,6 @@
   private String mServletPath = null;
   private String mPathInfo = null;
 
-  // Current Portlet phase
-  private Bridge.PortletPhase mPhase = null;
 
   @SuppressWarnings("unchecked")
   public PortletExternalContextImpl(PortletConfig portletConfig, PortletRequest portletRequest, 
@@ -144,8 +142,6 @@
     mPortletRequest = mOrigPortletRequest = portletRequest;
     mPortletResponse = mOrigPortletResponse = portletResponse;
 
-    mPhase = (Bridge.PortletPhase) mPortletRequest.getAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
-
     mFacesMappings = (List<String>) mPortletRequest.getAttribute(FACES_MAPPING_ATTRIBUTE);
     
     // Because determining the view accesses request parameters -- delay until its demanded
@@ -200,56 +196,96 @@
     boolean nonFacesAction = false;
     QueryString queryStr = null;
     int queryStart = -1;
+    boolean isPortletURL = false;
+    Bridge.PortletPhase urlType = getPortletPhase();
 
-    if (url.startsWith("#") || isExternalURL(url) || isDirectLink(url))
+    // 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).
+    if (isPortletURL(url))
     {
-      return url;
+      isPortletURL = true;
+      nonFacesAction = true;
+      //URL is of the form scheme:urlType?queryString
+      // remove the scheme
+      path = url.substring(url.indexOf(":")+ 1);
+      queryStart = url.indexOf('?');
+
+      if (queryStart != -1)
+      {
+        // Get the query string
+        queryStr = new QueryString(path.substring(queryStart + 1), "UTF8");
+        path = path.substring(0, queryStart);
+      }
+      
+      if (path.equalsIgnoreCase("render"))
+      {
+        urlType = Bridge.PortletPhase.RENDER_PHASE;
+      }
+      else if (path.equalsIgnoreCase("action"))
+      {
+        urlType = Bridge.PortletPhase.ACTION_PHASE;
+      }
+      else
+      {
+        log("PortletExternalContextImpl.encodeActionURL:  malformed portlet url "
+            + url);
+        return url;
+      }
     }
-
-    // url might contain DirectLink=false parameter -- spec says remove if
-    // it does.
-    url = removeDirectLink(url);
-
-    // Now determine the target viewId
-
-    // First: split URL into path and query string
-    // Hold onto QueryString for later processing
-    queryStart = url.indexOf('?');
-
-    if (queryStart != -1)
+    else if (url.startsWith("#") || isExternalURL(url) || isDirectLink(url))
     {
-      // Get the query string
-      queryStr = new QueryString(url.substring(queryStart + 1), "UTF8");
-      path = url.substring(0, queryStart);
+      return url;
     }
     else
     {
-      path = url;
-      // construct an empty queryString to hold the viewId
-      queryStr = new QueryString("UTF8");
-    }
+      // Its a Path encoded URL
+      
+      // url might contain DirectLink=false parameter -- spec says remove if
+      // it does.
+      url = removeDirectLink(url);
+
+      // Now determine the target viewId
+
+      // First: split URL into path and query string
+      // Hold onto QueryString for later processing
+      queryStart = url.indexOf('?');
+
+      if (queryStart != -1)
+      {
+        // Get the query string
+        queryStr = new QueryString(url.substring(queryStart + 1), "UTF8");
+        path = url.substring(0, queryStart);
+      }
+      else
+      {
+        path = url;
+        // construct an empty queryString to hold the viewId
+        queryStr = new QueryString("UTF8");
+      }
     
-    // Convert relative path to context path
-    if (isRelativePath(path))
-    {
-      path = getPathFromRelativePath(path);
-    }
+      // Convert relative path to context path
+      if (isRelativePath(path))
+      {
+        path = getPathFromRelativePath(path);
+      }
     
-    // Now se if this is a Faces URL
-    viewId = getViewIdFromPath(path);
+      // Now se if this is a Faces URL
+      viewId = getViewIdFromPath(path);
 
-    if (viewId != null)
-    {
-      encodeFacesActionTarget(queryStr, viewId);
-    }
-    else
-    {
-      // URL points at non-Faces action
-      nonFacesAction = true;
-      encodeNonFacesActionTarget(queryStr, path);
+      if (viewId != null)
+      {
+        encodeFacesActionTarget(queryStr, viewId);
+      }
+      else
+      {
+        // URL points at non-Faces action
+        nonFacesAction = true;
+        encodeNonFacesActionTarget(queryStr, path);
+      }
     }
     
-    if (mPhase == Bridge.PortletPhase.RENDER_PHASE)
+    if (getPortletPhase() == Bridge.PortletPhase.RENDER_PHASE)
     { // render - write
       // the viewId into
       // the response
@@ -260,7 +296,14 @@
       // Non-JSF actions are renderURLs as we merely dispatch to them
       if (nonFacesAction)
       {
-        actionURL = renderResponse.createRenderURL();
+        if (isPortletURL && urlType == Bridge.PortletPhase.ACTION_PHASE)
+        {
+          actionURL = renderResponse.createActionURL();
+        }
+        else
+        {
+          actionURL = renderResponse.createRenderURL();
+        }
       } 
       else
       {
@@ -401,10 +444,12 @@
       
       // In Portlet 1.0 we can't redirect to nonFaces target during render
       // Check for this case and throw an exception
-      if (mPhase == Bridge.PortletPhase.RENDER_PHASE)
+      // A NonFaces target is any that doesn't have a Faces ViewId
+      // encoded in it.
+      if (getPortletPhase() == Bridge.PortletPhase.RENDER_PHASE)
       {
-        String target = params.getParameter(NONJSF_TARGET_RENDER_PARAMETER);
-        if (target != null)
+        String target = params.getParameter(JSF_TARGET_VIEWID_RENDER_PARAMETER);
+        if (target == null)
         {
           throw new IllegalStateException("Can't redirect during render to a NonFaces target: " + target);
         }
@@ -414,7 +459,7 @@
     }
     else if ((url.startsWith("#") || isExternalURL(url) || isDirectLink(url)))
     {
-      if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
+      if (getPortletPhase() == Bridge.PortletPhase.ACTION_PHASE)
       {
         ((ActionResponse) getResponse()).sendRedirect(url);
         FacesContext.getCurrentInstance().responseComplete();
@@ -472,13 +517,16 @@
         s = URLUtils.convertFromRelative(path, s);
       }
 
-      // prepend the context path since portletResponse.encodeURL() requires a full path URI
-      // Don't need to check return from getRequestContextPath because there must
-      // always be a vlaue even if an empty string
-      String ctxPath = getRequestContextPath();
-      if (ctxPath.length() > 0 && !s.startsWith(ctxPath))
+      if (!isViewLink)
       {
-        s = ctxPath + s;
+        // prepend the context path since portletResponse.encodeURL() requires a full path URI
+        // Don't need to check return from getRequestContextPath because there must
+        // always be a vlaue even if an empty string
+        String ctxPath = getRequestContextPath();
+        if (ctxPath.length() > 0 && !s.startsWith(ctxPath))
+        {
+          s = ctxPath + s;
+        }
       }
     }
 
@@ -512,7 +560,7 @@
       throw new java.lang.NullPointerException();
     }
 
-    if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
+    if (getPortletPhase() == Bridge.PortletPhase.ACTION_PHASE)
     {
       throw new IllegalStateException("Request cannot be an ActionRequest");
     }
@@ -862,7 +910,7 @@
     throws UnsupportedEncodingException, IllegalStateException
   {
 
-    if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
+    if (getPortletPhase() == Bridge.PortletPhase.ACTION_PHASE)
     {
       ((ActionRequest) mPortletRequest).setCharacterEncoding(encoding);
     }
@@ -901,7 +949,7 @@
   @Override
   public String getRequestCharacterEncoding()
   {
-    if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
+    if (getPortletPhase() == Bridge.PortletPhase.ACTION_PHASE)
     {
       return ((ActionRequest) mPortletRequest).getCharacterEncoding();
     }
@@ -939,7 +987,7 @@
   @Override
   public String getRequestContentType()
   {
-    if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
+    if (getPortletPhase() == Bridge.PortletPhase.ACTION_PHASE)
     {
       return ((ActionRequest) mPortletRequest).getContentType();
     }
@@ -978,7 +1026,7 @@
   @Override
   public String getResponseCharacterEncoding()
   {
-    if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
+    if (getPortletPhase() == Bridge.PortletPhase.ACTION_PHASE)
     {
       throw new IllegalStateException("PortletExternalContextImpl.getResponseCharacterEncoding(): Response must be a RenderRequest");
     }
@@ -1013,7 +1061,7 @@
   @Override
   public String getResponseContentType()
   {
-    if (mPhase == Bridge.PortletPhase.ACTION_PHASE)
+    if (getPortletPhase() == Bridge.PortletPhase.ACTION_PHASE)
     {
       throw new IllegalStateException("PortletExternalContextImpl.getResponseContentType(): Response must be a RenderRequest");
     }
@@ -1073,35 +1121,62 @@
   }
 
   // End of JSF 1.2 API
+  
+  private Bridge.PortletPhase getPortletPhase()
+  {
+    return (Bridge.PortletPhase) getRequestMap().get(Bridge.PORTLET_LIFECYCLE_PHASE);
+  }
 
   /**
    * Gets the view identifier we should use for this request.
    */
   private String getViewId(boolean updateHistory)
-    throws BridgeDefaultViewNotSpecifiedException
+    throws BridgeDefaultViewNotSpecifiedException, BridgeInvalidViewPathException
   {
     boolean modeChanged = false;
     String requestedMode = mPortletRequest.getPortletMode().toString();
     
+    // See if the portlet has specified the target view
+    String viewId = (String) mPortletRequest.getAttribute(Bridge.VIEW_ID);
+    String viewPath = null;
+    if (viewId == null)
+    {
+      viewPath = (String) mPortletRequest.getAttribute(Bridge.VIEW_PATH);
+      if (viewPath != null)
+      {
+        //convert the view path into a viewId
+        viewId = getViewIdFromPath(viewPath);
+        if (viewId == null)
+        {
+          throw new BridgeInvalidViewPathException("Unable to resolve faces viewId: "
+              + viewPath);
+        }
+      }
+    }
+    
+    if (viewId == null)
+    {
     // Read the target from the request parameter
-    String viewId = mPortletRequest.getParameter(JSF_TARGET_VIEWID_RENDER_PARAMETER);
+      
+      viewId = mPortletRequest.getParameter(JSF_TARGET_VIEWID_RENDER_PARAMETER);
 
-    log("PortletExternalContextImpl.getViewId: found jsf target viewId = " + viewId);
+      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
-    if (viewId != null)
-    {
-      int i = viewId.indexOf(':');
-      if (i >= 0 )
+      // ViewIds stored in RenderParams are encoded with the Mode to which they apply
+      // Ensure current request Mode matches before using the viewId portion
+      if (viewId != null)
       {
-      
-        String mode = viewId.substring(0, i);
-        viewId = viewId.substring(i+1);
-        if (!mode.equalsIgnoreCase(requestedMode))
+        int i = viewId.indexOf(':');
+        if (i >= 0 )
         {
-          modeChanged = true;
-          viewId = null; // didn't match so don't use it
+      
+          String mode = viewId.substring(0, i);
+          viewId = viewId.substring(i+1);
+          if (!mode.equalsIgnoreCase(requestedMode))
+          {
+            modeChanged = true;
+            viewId = null; // didn't match so don't use it
+          }
         }
       }
     }
@@ -1156,9 +1231,7 @@
     // between modes and end up in the last view of the new mode
     // Note: only do in render phase becase we need to remember the 
     // render parameters -- during a render all parameters are render parameters
-    Map<String, Object> m = getRequestMap();
-    Bridge.PortletPhase phase = (Bridge.PortletPhase) m.get(Bridge.PORTLET_LIFECYCLE_PHASE);
-    if (updateHistory && phase == Bridge.PortletPhase.RENDER_PHASE)
+    if (updateHistory && getPortletPhase() == Bridge.PortletPhase.RENDER_PHASE)
     {
       updateViewChainAttribute(mPortletRequest.getPortletMode().toString(), viewId, modeChanged);
     }
@@ -1507,11 +1580,18 @@
     // so set the attribute they expect with the appropriate info.
     this.getRequestMap().put("com.sun.faces.INVOCATION_PATH", mapping);
   }
+  
+  private boolean isPortletURL(String url)
+  {
+    // Quick check for most common case
+    return url.toLowerCase().startsWith("portlet:");
+  }
 
 
   private boolean isAbsoluteURL(String url)
   {
     // Quick check for most common case
+    url = url.toLowerCase();
     if (url.startsWith("http:") || url.startsWith("https:"))
     {
       return true;
@@ -1658,7 +1738,7 @@
     this.getRequestMap().put(NO_SCOPE, Boolean.TRUE);
     
     // put the viewId in the QueryStr.
-    queryStr.setParameter(NONJSF_TARGET_RENDER_PARAMETER, target);
+    queryStr.setParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER, target);
   }