You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by de...@apache.org on 2017/09/17 12:29:41 UTC
[myfaces-trinidad] 02/03: Commit some experimental changes to
support a much more robust URL encoding scheme.
This is an automated email from the ASF dual-hosted git repository.
deki pushed a commit to branch sobryan-experimental-url-encoding-2
in repository https://gitbox.apache.org/repos/asf/myfaces-trinidad.git
commit ce50547b5c8e1c0692fa3b57f27b1d78574940e6
Author: Scott Bryan <so...@apache.org>
AuthorDate: Wed Jun 13 00:17:09 2012 +0000
Commit some experimental changes to support a much more robust URL encoding scheme.
---
.../myfaces/trinidad/resource/ResourceLoader.java | 7 +-
.../trinidad/util/ExternalContextURLEncoder.java | 48 +++++++++++++
.../myfaces/trinidad/util/PortletURLEncoder.java | 76 +++++++++++++++++++++
.../apache/myfaces/trinidad/util/URLEncoder.java | 75 ++++++++++++++++++++
.../myfaces/trinidad/util/URLEncoderFactory.java | 79 ++++++++++++++++++++++
.../myfaces/trinidad/util/URLEncoderWrapper.java | 41 +++++++++++
.../config/GlobalConfiguratorImpl.java | 3 +
.../config/URLEncoderExternalContext.java | 37 ++++++++++
8 files changed, 362 insertions(+), 4 deletions(-)
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/resource/ResourceLoader.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/resource/ResourceLoader.java
index c147b3e..928e973 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/resource/ResourceLoader.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/resource/ResourceLoader.java
@@ -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
*
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ExternalContextURLEncoder.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ExternalContextURLEncoder.java
new file mode 100644
index 0000000..ddc64c9
--- /dev/null
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ExternalContextURLEncoder.java
@@ -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;
+}
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/PortletURLEncoder.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/PortletURLEncoder.java
new file mode 100644
index 0000000..d066180
--- /dev/null
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/PortletURLEncoder.java
@@ -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();
+ }
+}
+
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoder.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoder.java
new file mode 100644
index 0000000..614c0c7
--- /dev/null
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoder.java
@@ -0,0 +1,75 @@
+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.
+ *
+ * @param url
+ * @return
+ */
+ public abstract String encodePartialActionURL(String url);
+
+ /**
+ * Encodes a url for redirect.
+ *
+ * @param url
+ * @return
+ */
+ public abstract String encodeRedirectURL(String url);
+
+ public abstract String encodeResourceURL(String url);
+
+ /**
+ * Encodes a url to a static resource. This url *MAY* share the same session
+ * as the overall page or it may not. The advantage of encoding something as
+ * a static resource is that in certain types of containers, like portals, the
+ * URL generated by this encoding may work better for the purposes of caching.
+ *
+ * @param url
+ * @return
+ */
+ 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);
+}
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderFactory.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderFactory.java
new file mode 100644
index 0000000..0df30eb
--- /dev/null
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderFactory.java
@@ -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();
+
+}
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderWrapper.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderWrapper.java
new file mode 100644
index 0000000..45ddf31
--- /dev/null
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/URLEncoderWrapper.java
@@ -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);
+ }
+}
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java
index d7dfbe8..68f67eb 100644
--- a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java
@@ -322,6 +322,9 @@ public final class GlobalConfiguratorImpl
{
RequestStateMap state = RequestStateMap.getInstance(ec);
RequestType type = (RequestType) state.get(_REQUEST_TYPE);
+
+ //Install the URLEncoder plugin system
+ ec = new URLEncoderExternalContext(ec);
if (type == null)
{
diff --git a/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/URLEncoderExternalContext.java b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/URLEncoderExternalContext.java
new file mode 100644
index 0000000..83695a4
--- /dev/null
+++ b/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/URLEncoderExternalContext.java
@@ -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;
+}
--
To stop receiving notification emails like this one, please contact
"commits@myfaces.apache.org" <co...@myfaces.apache.org>.