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 2012/07/02 21:08:24 UTC

svn commit: r1356417 - in /myfaces/trinidad/branches/sobryan-experimental-url-encoding-3: trinidad-api/src/main/java/org/apache/myfaces/trinidad/resource/ trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ trinidad-impl/src/main/java/org/apac...

Author: sobryan
Date: Mon Jul  2 19:08:22 2012
New Revision: 1356417

URL: http://svn.apache.org/viewvc?rev=1356417&view=rev
Log:
Some experimental URL encoding features

Added:
    myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ExternalContextURLEncoder.java
    myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/PortletURLEncoder.java
    myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoder.java
    myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderFactory.java
    myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderWrapper.java
    myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/URLEncoderExternalContext.java
Modified:
    myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/resource/ResourceLoader.java
    myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java

Modified: myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/resource/ResourceLoader.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/resource/ResourceLoader.java?rev=1356417&r1=1356416&r2=1356417&view=diff
==============================================================================
--- myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/resource/ResourceLoader.java (original)
+++ myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/resource/ResourceLoader.java Mon Jul  2 19:08:22 2012
@@ -49,10 +49,9 @@ public class ResourceLoader
    * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
    * identifies the resource.
    *
-   * <p> This method will first search the this resource loader for the
-   * resource.  That failing, this method will invoke 
-   * {@link #findResource(String)} to on the parent resource loader to
-   * find the resource.  </p>
+   * <p> This method will first invoke {@link #findResource(String)} to find the
+   * resource.  Failing that, the method will invoke <code>getResource(String)</code>
+   * on the parent.</p>
    *
    * @param  name  the resource name
    *

Added: myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ExternalContextURLEncoder.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ExternalContextURLEncoder.java?rev=1356417&view=auto
==============================================================================
--- myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ExternalContextURLEncoder.java (added)
+++ myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ExternalContextURLEncoder.java Mon Jul  2 19:08:22 2012
@@ -0,0 +1,48 @@
+package org.apache.myfaces.trinidad.util;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+
+class ExternalContextURLEncoder extends URLEncoder
+{
+  public ExternalContextURLEncoder(ExternalContext ec)
+  {
+    assert(ec != null);
+    _context = ec;
+  }
+  
+  @Override
+  public String encodePartialActionURL(String url)
+  {
+    return _context.encodeActionURL(url);
+  }
+
+  public String encodeRedirectURL(String url)
+  {
+    return url;
+  }
+
+  public String encodeInProtocolResourceURL(String url)
+  {
+    return _context.encodeResourceURL(url);
+  }
+
+  public String encodeSkinResourceURL(String url)
+  {
+    return url;
+  }
+
+  @Override
+  public String encodeActionURL(String url)
+  {
+    return _context.encodeActionURL(url);
+  }
+  
+  @Override
+  public String encodeResourceURL(String url)
+  {
+    return _context.encodeResourceURL(url);
+  }
+  
+  private ExternalContext _context;
+}

Added: myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/PortletURLEncoder.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/PortletURLEncoder.java?rev=1356417&view=auto
==============================================================================
--- myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/PortletURLEncoder.java (added)
+++ myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/PortletURLEncoder.java Mon Jul  2 19:08:22 2012
@@ -0,0 +1,76 @@
+package org.apache.myfaces.trinidad.util;
+
+import java.net.URI;
+
+import javax.faces.context.ExternalContext;
+
+/**
+ *
+ */
+class PortletURLEncoder extends ExternalContextURLEncoder
+{
+  public PortletURLEncoder(ExternalContext ec)
+  {
+    super(ec);
+  }
+
+  @Override
+  public String encodeInProtocolResourceURL(String url)
+  {
+    return super.encodeInProtocolResourceURL(_addParam(url, "javax.portlet.faces.InProtocolResourceLink", "true"));
+  }
+
+  @Override
+  public String encodePartialActionURL(String url)
+  {
+    //Portlet AJAX requests are encoded as InProtocolResource urls
+    return encodeInProtocolResourceURL(url);
+  }
+  
+  //Adds or replaces a parameter value
+  private String _addParam(String url, String name, String value)
+  {
+    int queryPos = url.indexOf('?');
+    int fragmentPos = url.lastIndexOf('#');
+    name += "="; //Add the equals sign to this, every use of it below needs the "=" sign.
+    
+    StringBuilder sb = new StringBuilder();
+    
+    
+    if(queryPos == -1)
+    {
+      sb.append((fragmentPos == -1)?url:url.substring(0, fragmentPos))
+        .append("?")
+        .append(name)
+        .append(value);
+      
+    }
+    else
+    {
+      sb.append(url.substring(0, ++queryPos)); //We must include the "?"
+      String queryString = (fragmentPos == -1)?url.substring(queryPos):url.substring(queryPos, fragmentPos);
+      
+      //Search the queryString to see if the param already exists.  If it does, change it.
+      if(queryString.indexOf(name) != -1)
+      {
+        //We have this query param already.  Replace all occurances of it with the new name/value
+        queryString = queryString.replaceAll(name + "[\\w+.~*$\'()*\\-+;,?/]*", name + value);
+      }
+      else
+      {
+        queryString += "&" + name + value;
+      }
+      
+      sb.append(queryString);
+    }
+    
+    //Append the fragment if there is one
+    if(fragmentPos >= 0)
+    {
+      sb.append(url.substring(fragmentPos));
+    }
+    
+    return sb.toString();
+  }
+}
+

Added: myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoder.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoder.java?rev=1356417&view=auto
==============================================================================
--- myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoder.java (added)
+++ myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoder.java Mon Jul  2 19:08:22 2012
@@ -0,0 +1,99 @@
+package org.apache.myfaces.trinidad.util;
+
+import java.io.Serializable;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+
+/**
+ * Encodes URL's based on thier type.  While the ExternalContext does this to
+ * some extent, the types of URL's it encodes are often ill-defined.  This utility
+ * method allows the caller to ensure that URL's are encoded in the proper fashion
+ * depending on which container is active at the time.
+ * <p/>
+ * Out of the box, this class supports Servlet and Portlet encoding, but it may
+ * be extended on a per-request basis to support other types of URL encoding with
+ * the use of the "registerURLEncoder" method.
+ * <p/>
+ * It is also important to note that this does not impact the encoding done by the
+ * ExternalContext.  As such, all current applications should work without
+ * modification if they do not choose to use this API for encoding.
+ */
+public abstract class URLEncoder
+{
+  /**
+   * This function should be the same as the {@link ExternalContext#encodeActionURL(String)}
+   * method.  By default it call the code in the ExternalContext.  The reason its
+   * provided here is that certain URLEncoderUtility instances may wish to override
+   * the default functionality and have the ExternalContext pull its default encoding
+   * from here.
+   */
+  public abstract String encodeActionURL(String url);
+  
+  /**
+   * This encodes a URL so that it can be used to make a PPR request in all containers.
+   * JSF 2.0 has the ability to encode URL's in such a fashion, but this is missing
+   * from JSF 1.2 containers.  This method provides the same functionality for JSF 1.2.
+   * 
+   * @param url the unencoded url
+   * @return the encoded url
+   * 
+   * @throws IllegalArgumentException if the URL cannot be encoded
+   */
+  public abstract String encodePartialActionURL(String url);
+  
+  /**
+   * Encodes a url to be explicitly used for a redirect.  In some containers, this is
+   * encoded as-is.  In other containers this may not be encoded or must contain a
+   * fully qualified url.
+   * 
+   * @param url the unencoded url
+   * @return the encoded url
+   * 
+   * @throws IllegalArgumentException if the URL cannot be encoded
+   */
+  public abstract String encodeRedirectURL(String url);
+  
+  /**
+   * Encodes a url as a resource.  Generally speaking this will be equivalent to
+   * {@link ExternalContext#encodeResourceURL(String)}.  The url returned from this
+   * method is NOT guarenteed to be in-protocol (meaning that it MAY not have access
+   * to session information).  The advantage of encoding something in this fashion
+   * is that in certain types of containers, like portals, the URL generated may 
+   * have faster access and will generally work better for the purposes of caching
+   * do to its RESTful state.
+   * 
+   * @param url the unencoded url
+   * @return the encoded url
+   * 
+   * @throws IllegalArgumentException if the URL cannot be encoded
+   */
+  public abstract String encodeResourceURL(String url);
+  
+  /**
+   * Encodes a url to a resource such that it is inProtocol.  This means that the
+   * URL returned will be encoded in such a way that the resource will have access
+   * to the parent application's session.  While these URL's do have access to the
+   * session information, they may not be written in a format that is easily cachable.
+   * 
+   * @param url the unencoded url
+   * @return the encoded url
+   * 
+   * @throws IllegalArgumentException if the URL cannot be encoded
+   */
+  public abstract String encodeInProtocolResourceURL(String url);
+  
+  /**
+   * Encodes a resource URL that is mapped to a skinning resources.  Trinidad has
+   * an extensive skinning system that allows for extraction of certain properties
+   * like images so that they can be used with the componentry.  Generally these
+   * image resources are on the same server and whatnot as the actual skin.  In
+   * a servlet environment, this is always the same server, but in portal-like
+   * environments these resources may be on different servers.  This encodes a
+   * URL that comes from a skin and sends it to the right location.
+   * 
+   * @param url
+   * @return
+   */
+  public abstract String encodeSkinResourceURL(String url);
+}

Added: myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderFactory.java?rev=1356417&view=auto
==============================================================================
--- myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderFactory.java (added)
+++ myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderFactory.java Mon Jul  2 19:08:22 2012
@@ -0,0 +1,79 @@
+package org.apache.myfaces.trinidad.util;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+
+/**
+ * This is a factory for the URLEncoder.  The URL encoder is a convenience class that
+ * handles URL encoding in a container independant fashion.  The Portlet bridge spec
+ * and later JSF specifications have tried to make URL encoding more specific, but
+ * these technologies do not always address the needs of Trinidad URL encoding in
+ * all circumstances.  This method aims to do just that.
+ */
+public class URLEncoderFactory
+{
+  public static URLEncoderFactory getFactory()
+  {
+    return _ENCODER;
+  }
+  
+  public URLEncoder getURLEncoder()
+  {
+    FacesContext fc = FacesContext.getCurrentInstance();
+    if(null == fc)
+    {
+      return getURLEncoder(null);
+    }
+
+    return getURLEncoder(fc.getExternalContext());
+  }
+  
+  /**
+   * Returns a URLEncoder for this request.
+   * 
+   * @return a URLEncoder for the given request
+   * @throws IllegalStateException when there is not FacesContext available and
+   *         a URLEncoder has not been manually set.  This can also be thrown if
+   *         the URLEncoder has already been cleaned up at the end of the request.
+   */
+  public URLEncoder getURLEncoder(ExternalContext ec)
+  {
+    //even though we should wait until we have a faces context and throw an error
+    //if we don't, go ahead and fudge it if the threadlocal is not null.  This just
+    //means that a URLEncoder has already been set for this thread.
+    URLEncoder enc = _local.get();
+    
+    if(null != enc)
+    {
+      return enc;
+    }
+    
+    if(null == ec)
+    {
+      throw new IllegalStateException("An ExternalContext must be a available");
+    }
+    
+    if(ExternalContextUtils.isPortlet(ec))
+    {
+      setURLEncoder(new PortletURLEncoder(ec));
+    }
+    else
+    {
+      setURLEncoder(new ExternalContextURLEncoder(ec));
+    }
+    
+    return _local.get();
+  }
+  
+  public void setURLEncoder(URLEncoder encoder)
+  {
+    _local.set(encoder);
+  }
+  
+  private static final URLEncoderFactory _ENCODER = new URLEncoderFactory();
+  
+  //This threadlocal should get cleaned up when the request is done.  It's handled
+  //by the configurators.
+  private static final ThreadLocal<URLEncoder> _local = ThreadLocalUtils.newRequestThreadLocal();
+  
+}

Added: myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderWrapper.java?rev=1356417&view=auto
==============================================================================
--- myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderWrapper.java (added)
+++ myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderWrapper.java Mon Jul  2 19:08:22 2012
@@ -0,0 +1,41 @@
+package org.apache.myfaces.trinidad.util;
+
+public abstract class URLEncoderWrapper
+  extends URLEncoder
+{
+  public abstract URLEncoder getWrapped();
+  
+  public String encodeActionURL(String url)
+  {
+    return getWrapped().encodeActionURL(url);
+  }
+
+  public String encodeResourceURL(String url)
+  {
+    return getWrapped().encodeResourceURL(url);
+  }
+
+  @Override
+  public String encodeInProtocolResourceURL(String url)
+  {
+    return getWrapped().encodeInProtocolResourceURL(url);
+  }
+
+  @Override
+  public String encodePartialActionURL(String url)
+  {
+    return getWrapped().encodePartialActionURL(url);
+  }
+
+  @Override
+  public String encodeRedirectURL(String url)
+  {
+    return getWrapped().encodeRedirectURL(url);
+  }
+
+  @Override
+  public String encodeSkinResourceURL(String url)
+  {
+    return getWrapped().encodeSkinResourceURL(url);
+  }
+}

Modified: myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java?rev=1356417&r1=1356416&r2=1356417&view=diff
==============================================================================
--- myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java (original)
+++ myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java Mon Jul  2 19:08:22 2012
@@ -322,6 +322,9 @@ public final class GlobalConfiguratorImp
   {
     RequestStateMap state = RequestStateMap.getInstance(ec);
     RequestType type = (RequestType) state.get(_REQUEST_TYPE);
+    
+    //Install the URLEncoder plugin system
+    ec = new URLEncoderExternalContext(ec);
 
     if (type == null)
     {

Added: myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/URLEncoderExternalContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/URLEncoderExternalContext.java?rev=1356417&view=auto
==============================================================================
--- myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/URLEncoderExternalContext.java (added)
+++ myfaces/trinidad/branches/sobryan-experimental-url-encoding-3/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/URLEncoderExternalContext.java Mon Jul  2 19:08:22 2012
@@ -0,0 +1,37 @@
+package org.apache.myfaces.trinidadinternal.config;
+
+import javax.faces.context.ExternalContext;
+
+import org.apache.myfaces.trinidad.context.ExternalContextDecorator;
+import org.apache.myfaces.trinidad.util.URLEncoder;
+import org.apache.myfaces.trinidad.util.URLEncoderFactory;
+
+public class URLEncoderExternalContext
+  extends ExternalContextDecorator
+{
+  public URLEncoderExternalContext(ExternalContext ec)
+  {
+    _ec = ec;
+  }
+
+  protected ExternalContext getExternalContext()
+  {
+    return _ec;
+  }
+
+  @Override
+  public String encodeResourceURL(String url)
+  {
+    URLEncoder encoder = URLEncoderFactory.getFactory().getURLEncoder(_ec);
+    return encoder.encodeResourceURL(url);
+  }
+
+  @Override
+  public String encodeActionURL(String url)
+  {
+    URLEncoder encoder = URLEncoderFactory.getFactory().getURLEncoder(_ec);
+    return encoder.encodeActionURL(url);
+  }
+  
+  private ExternalContext _ec;
+}