Modify AssetDispatcher to handle two path prefixes: normal and compressed

Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/aa465fcd
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/aa465fcd
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/aa465fcd

Branch: refs/heads/master
Commit: aa465fcd3b4b735da9682f377e43553110303494
Parents: 6fd011e
Author: Howard M. Lewis Ship <[email protected]>
Authored: Sat Apr 13 08:25:00 2013 -0700
Committer: Howard M. Lewis Ship <[email protected]>
Committed: Mon Apr 15 22:11:18 2013 +0100

----------------------------------------------------------------------
 .../src/main/java/org/apache/tapestry5/Asset.java  |    5 ++
 .../java/org/apache/tapestry5/SymbolConstants.java |   12 +++-
 .../internal/services/AssetDispatcher.java         |   50 +++++++++++----
 .../tapestry5/services/assets/AssetsModule.java    |    1 +
 4 files changed, 55 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/aa465fcd/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
index b2c76ac..a7a9f25 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
@@ -40,8 +40,13 @@ public interface Asset
      * <p/>Note that starting in Tapestry 5.4, it is expected that Asset 
instances recognize
      * when the underlying Resource's content has changed, and update the 
clientURL to reflect the new content's
      * checksum. This wasn't an issue in earlier releases where the clientURL 
incorporated a version number.
+     * <p/>
+     * Finally, starting in 5.4, this value will often be <em>variant</em>: 
the exact URL returned will depend on
+     * whether the underlying resource content is compressable, whether the 
current {@link org.apache.tapestry5.services.Request}
+     * supports compression.
      *
      * @see org.apache.tapestry5.services.AssetSource
+     * @see org.apache.tapestry5.services.AssetPathConverter
      */
     String toClientURL();
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/aa465fcd/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java
----------------------------------------------------------------------
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java
index 0d671c4..8f16694 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java
@@ -330,11 +330,21 @@ public class SymbolConstants
     /**
      * Prefix to be used for all resource paths, used to recognize which 
requests are for assets. This value
      * is appended to the context path and the (optional {@linkplain 
#APPLICATION_FOLDER application folder}.
-     * Its default is "assets".  It may contain slashes, but should not begin 
or end with one.
+     * Its default is "assets".  It may contain slashes, but should not begin 
or end with one. This is the prefix
+     * for uncompressed assets.
      */
     public static final String ASSET_PATH_PREFIX = 
"tapestry.asset-path-prefix";
 
     /**
+     * As with {@link #ASSET_PATH_PREFIX} but for compressed versions of 
assets. At render time, it is determined
+     * whether each asset is compressable (for example, image file formats are 
already compressed). A path for
+     * either {@link #ASSET_PATH_PREFIX} or this prefix is selected at render 
time.  Defaults to the asset path prefix suffixed with ".gz".
+     *
+     * @since 5.4
+     */
+    public static final String COMPRESSED_ASSET_PATH_PREFIX = 
"tapestry.compressed-asset-path-prefix";
+
+    /**
      * The Asset path to the copy of Require JS to include in rendered pages. 
Any page that makes use of any JavaScript will
      * automatically import this library (as well as the core JavaScript 
stack).
      *

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/aa465fcd/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetDispatcher.java
----------------------------------------------------------------------
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetDispatcher.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetDispatcher.java
index 4f8e8a7..2ab1a68 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetDispatcher.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetDispatcher.java
@@ -30,8 +30,10 @@ import java.util.List;
 import java.util.Map;
 
 /**
- * Recognizes requests where the path begins with "/asset/" and delivers the 
content therein as a bytestream. Also
- * handles requests that are simply polling for a change to the file.
+ * Recognizes requests where the path begins with "/asset/" (actually, as 
defined by the
+ * {@link SymbolConstants#ASSET_PATH_PREFIX} symbol), and delivers the content 
therein as a bytestream. Also
+ * handles requests that are simply polling for a change to the file 
(including checking the ETag in the
+ * request against {@linkplain 
org.apache.tapestry5.services.assets.StreamableResource#getChecksum() the 
asset's checksum}.
  *
  * @see ResourceStreamer
  * @see ClasspathAssetAliasManager
@@ -51,26 +53,27 @@ public class AssetDispatcher implements Dispatcher
      */
     private final List<String> assetPaths = CollectionFactory.newList();
 
-    private final String pathPrefix;
+    private final String uncompressedPathPrefix, compressedPathPrefix;
 
     public AssetDispatcher(Map<String, AssetRequestHandler> configuration,
 
                            PathConstructor pathConstructor,
 
                            @Symbol(SymbolConstants.ASSET_PATH_PREFIX)
-                           String assetPathPrefix)
+                           String uncompressedPrefix,
+
+                           
@Symbol(SymbolConstants.COMPRESSED_ASSET_PATH_PREFIX)
+                           String compressedPrefix)
     {
-        pathPrefix = pathConstructor.constructDispatchPath(assetPathPrefix, 
"");
+        uncompressedPathPrefix = 
pathConstructor.constructDispatchPath(uncompressedPrefix, "");
+        compressedPathPrefix = 
pathConstructor.constructDispatchPath(compressedPrefix, "");
 
         for (String path : configuration.keySet())
         {
-            String extendedPath = path.length() == 0
-                    ? pathPrefix
-                    : pathPrefix + path + "/";
-
-            pathToHandler.put(extendedPath, configuration.get(path));
+            AssetRequestHandler handler = configuration.get(path);
 
-            assetPaths.add(extendedPath);
+            addPath(uncompressedPathPrefix, path, handler);
+            addPath(compressedPathPrefix, path, handler);
         }
 
         // Sort by descending length
@@ -84,6 +87,29 @@ public class AssetDispatcher implements Dispatcher
         });
     }
 
+    private void addPath(String prefix, String path, AssetRequestHandler 
handler)
+    {
+        String extendedPath = buildPath(prefix, path);
+
+        pathToHandler.put(extendedPath, handler);
+
+        assetPaths.add(extendedPath);
+    }
+
+    private String buildPath(String prefix, String path)
+    {
+        // TODO: Not sure when path would be length 0!
+        return path.length() == 0
+                ? prefix
+                : prefix + path + "/";
+    }
+
+    private boolean matchesEitherPrefix(String path)
+    {
+        return path.startsWith(compressedPathPrefix) ||
+                path.startsWith(uncompressedPathPrefix);
+    }
+
     public boolean dispatch(Request request, Response response) throws 
IOException
     {
         String path = request.getPath();
@@ -91,7 +117,7 @@ public class AssetDispatcher implements Dispatcher
         // Remember that the request path does not include the context path, 
so we can simply start
         // looking for the asset path prefix right off the bat.
 
-        if (!path.startsWith(pathPrefix))
+        if (!matchesEitherPrefix(path))
         {
             return false;
         }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/aa465fcd/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetsModule.java
----------------------------------------------------------------------
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetsModule.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetsModule.java
index ad954c0..797e464 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetsModule.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetsModule.java
@@ -76,6 +76,7 @@ public class AssetsModule
         configuration.add(SymbolConstants.ASSET_URL_FULL_QUALIFIED, false);
 
         configuration.add(SymbolConstants.ASSET_PATH_PREFIX, "assets");
+        configuration.add(SymbolConstants.COMPRESSED_ASSET_PATH_PREFIX, 
"${tapestry.asset-path-prefix}.gz");
     }
 
     // The use of decorators is to allow third-parties to get their own 
extensions

Reply via email to