You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2013/03/15 00:09:18 UTC

[10/14] git commit: Gut and deprecate ResourceDigestManager and ResourceDigestGenerator - all assets now include a checksum in the URL, rather than just selected file extensions for classpath resources

Gut and deprecate ResourceDigestManager and ResourceDigestGenerator
- all assets now include a checksum in the URL, rather than just selected file extensions for classpath resources


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

Branch: refs/heads/master
Commit: b3428cc3c0db0a4d71b16cdd4a52f374dec7d6c2
Parents: 373f5cf
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Thu Mar 14 13:37:44 2013 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Thu Mar 14 13:41:12 2013 -0700

----------------------------------------------------------------------
 .../internal/services/AssetDispatcher.java         |    3 -
 .../internal/services/AssetResourceLocator.java    |   40 ---
 .../services/AssetResourceLocatorImpl.java         |   96 -------
 .../internal/services/ClasspathAssetFactory.java   |   31 +--
 .../internal/services/InternalModule.java          |    3 +-
 .../services/ResourceDigestGeneratorImpl.java      |   68 +-----
 .../internal/services/ResourceDigestManager.java   |   10 +
 .../services/ResourceDigestManagerImpl.java        |   71 +-----
 .../assets/ClasspathAssetRequestHandler.java       |   17 +-
 .../services/ResourceDigestGenerator.java          |   13 +-
 .../apache/tapestry5/services/TapestryModule.java  |   29 +--
 .../tapestry5/services/assets/AssetsModule.java    |    7 +-
 .../apache/tapestry5/test/TapestryTestCase.java    |   10 -
 .../src/test/app1/AssetProtectionDemo.tml          |   30 ++-
 .../integration/app1/AssetDigestTests.groovy       |   75 ------
 .../integration/app1/services/AppModule.java       |    1 +
 .../services/ClasspathAssetFactoryTest.java        |   41 +---
 .../services/ResourceDigestGeneratorImplTest.java  |   78 ------
 .../services/ResourceDigestManagerTest.java        |  195 ---------------
 .../internal/test/InternalBaseTestCase.java        |   10 -
 20 files changed, 67 insertions(+), 761 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/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 0f64f73..4f8e8a7 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
@@ -55,9 +55,6 @@ public class AssetDispatcher implements Dispatcher
 
     public AssetDispatcher(Map<String, AssetRequestHandler> configuration,
 
-                           @Symbol(SymbolConstants.APPLICATION_FOLDER)
-                           String applicationFolder,
-
                            PathConstructor pathConstructor,
 
                            @Symbol(SymbolConstants.ASSET_PATH_PREFIX)

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocator.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocator.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocator.java
deleted file mode 100644
index 7746301..0000000
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocator.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2009, 2010 The Apache Software Foundation
-//
-// Licensed 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 org.apache.tapestry5.internal.services;
-
-import java.io.IOException;
-
-import org.apache.tapestry5.ioc.Resource;
-
-/**
- * Responsible for converting a path into a {@link org.apache.tapestry5.ioc.Resource} that can be
- * {@linkplain org.apache.tapestry5.internal.services.ResourceStreamer
- * streamed to the client}. The path is on the classpath, but may have been changed to include a checksum (in
- * certain cases).
- * 
- * @since 5.1.0.2
- */
-public interface AssetResourceLocator
-{
-    /**
-     * For a complete classpath path, returns the Resource for the path. This include checking for a
-     * digest for protected files.
-     * 
-     * @return
-     *         resource corresponding to path (may be for a non-existent resource), or null if path is invalid (i.e.,
-     *         incorrect digest)
-     */
-    Resource findClasspathResourceForPath(String path) throws IOException;
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocatorImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocatorImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocatorImpl.java
deleted file mode 100644
index 1852154..0000000
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocatorImpl.java
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2009, 2010, 2011 The Apache Software Foundation
-//
-// Licensed 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 org.apache.tapestry5.internal.services;
-
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.tapestry5.ioc.Resource;
-import org.apache.tapestry5.services.AssetSource;
-import org.apache.tapestry5.services.Response;
-
-public class AssetResourceLocatorImpl implements AssetResourceLocator
-{
-    private final ResourceDigestManager digestManager;
-
-    private final Response response;
-
-    private final AssetSource assetSource;
-
-    public AssetResourceLocatorImpl(ResourceDigestManager digestManager, Response response, AssetSource assetSource)
-    {
-        this.digestManager = digestManager;
-        this.response = response;
-        this.assetSource = assetSource;
-    }
-
-    public Resource findClasspathResourceForPath(String path) throws IOException
-    {
-        Resource resource = assetSource.resourceForPath(path);
-
-        if (!digestManager.requiresDigest(resource))
-            return resource;
-
-        return validateChecksumOfClasspathResource(resource);
-    }
-
-    /**
-     * Validates the checksum encoded into the resource, and returns the true resource (with the checksum
-     * portion removed from the file name).
-     */
-    private Resource validateChecksumOfClasspathResource(Resource resource) throws IOException
-    {
-        String file = resource.getFile();
-
-        // Somehow this code got real ugly, but it's all about preventing NPEs when a resource
-        // that should have a digest doesn't.
-
-        boolean valid = false;
-        Resource result = resource;
-
-        int lastdotx = file.lastIndexOf('.');
-
-        if (lastdotx > 0)
-        {
-            int prevdotx = file.lastIndexOf('.', lastdotx - 1);
-
-            if (prevdotx > 0)
-            {
-                String requestDigest = file.substring(prevdotx + 1, lastdotx);
-
-                // Strip the digest out of the file name.
-
-                String realFile = file.substring(0, prevdotx) + file.substring(lastdotx);
-
-                result = resource.forFile(realFile);
-
-                String actualDigest = digestManager.getDigest(result);
-
-                valid = requestDigest.equals(actualDigest);
-            }
-        }
-
-        if (valid)
-            return result;
-
-        // TODO: Perhaps we should send an exception here, so that the caller can decide
-        // to send the error. I'm not happy with this.
-
-        response.sendError(HttpServletResponse.SC_FORBIDDEN, String.format("The asset digest in the request does not match the actual digest for asset '%s'. This indicates that the content of the asset has changed between requests.", result.getPath()));
-
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
index de96d0f..46c02fc 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
@@ -24,16 +24,13 @@ import org.apache.tapestry5.services.ClasspathAssetAliasManager;
 import org.apache.tapestry5.services.ClasspathProvider;
 
 /**
- * Generates Assets for files on the classpath. Caches generated client URLs internally, and clears that cache when
- * notified to do so by the {@link ResourceDigestManager}.
+ * Generates Assets for files on the classpath.
  *
  * @see AssetDispatcher
  */
 @Marker(ClasspathProvider.class)
 public class ClasspathAssetFactory implements AssetFactory
 {
-    private final ResourceDigestManager digestManager;
-
     private final ClasspathAssetAliasManager aliasManager;
 
     private final ClasspathResource rootResource;
@@ -42,10 +39,8 @@ public class ClasspathAssetFactory implements AssetFactory
 
     private final boolean invariant;
 
-    public ClasspathAssetFactory(ResourceDigestManager digestManager, ClasspathAssetAliasManager aliasManager,
-                                 AssetPathConverter converter)
+    public ClasspathAssetFactory(ClasspathAssetAliasManager aliasManager, AssetPathConverter converter)
     {
-        this.digestManager = digestManager;
         this.aliasManager = aliasManager;
         this.converter = converter;
 
@@ -56,27 +51,9 @@ public class ClasspathAssetFactory implements AssetFactory
 
     private String clientURL(Resource resource)
     {
-        String defaultPath = buildDefaultPath(resource);
-
-        return converter.convertAssetPath(defaultPath);
-    }
-
-    private String buildDefaultPath(Resource resource)
-    {
-        boolean requiresDigest = digestManager.requiresDigest(resource);
-
-        String path = resource.getPath();
-
-        if (requiresDigest)
-        {
-            // Resources with extensions go from foo/bar/baz.txt --> foo/bar/baz.CHECKSUM.txt
-
-            int lastdotx = path.lastIndexOf('.');
-
-            path = path.substring(0, lastdotx + 1) + digestManager.getDigest(resource) + path.substring(lastdotx);
-        }
+        String assetPath = aliasManager.toClientURL(resource);
 
-        return aliasManager.toClientURL(resource);
+        return converter.convertAssetPath(assetPath);
     }
 
     public Asset createAsset(Resource resource)

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
index b3f694e..e3911fa 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
@@ -60,10 +60,9 @@ public class InternalModule
         binder.bind(EndOfRequestEventHub.class);
         binder.bind(ResponseCompressionAnalyzer.class, ResponseCompressionAnalyzerImpl.class);
         binder.bind(ComponentModelSource.class);
-        binder.bind(AssetResourceLocator.class);
         binder.bind(JavaScriptStackPathConstructor.class);
         binder.bind(AjaxFormUpdateController.class);
-        binder.bind(ResourceDigestManager.class, ResourceDigestManagerImpl.class);
+        binder.bind(ResourceDigestManager.class, ResourceDigestManagerImpl.class);  // Remove in Tapestry 5.5
         binder.bind(RequestPageCache.class, RequestPageCacheImpl.class);
         binder.bind(ComponentInstantiatorSource.class);
         binder.bind(InternalComponentInvalidationEventHub.class);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestGeneratorImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestGeneratorImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestGeneratorImpl.java
index 36e6907..5c819cc 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestGeneratorImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestGeneratorImpl.java
@@ -14,86 +14,24 @@
 
 package org.apache.tapestry5.internal.services;
 
-import org.apache.commons.codec.binary.Hex;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.services.ResourceDigestGenerator;
 
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
 import java.net.URL;
-import java.security.MessageDigest;
-import java.util.Collection;
-import java.util.Set;
 
 /**
- * Implementation of {@link ResourceDigestGenerator} that generates MD5 digests.
+ * Gutted implementation; will be removed in Tapestry 5.5.
  */
 public class ResourceDigestGeneratorImpl implements ResourceDigestGenerator
 {
-    private static final int BUFFER_SIZE = 5000;
-
-    private final Set<String> digestExtensions;
-
-    public ResourceDigestGeneratorImpl(Collection<String> configuration)
-    {
-        digestExtensions = CollectionFactory.newSet(configuration);
-    }
-
     public String generateDigest(URL url)
     {
-        InputStream stream = null;
-
-        try
-        {
-            MessageDigest digest = MessageDigest.getInstance("MD5");
-
-            stream = new BufferedInputStream(url.openStream());
-
-            digestStream(digest, stream);
-
-            stream.close();
-            stream = null;
-
-            byte[] bytes = digest.digest();
-            char[] encoded = Hex.encodeHex(bytes);
-
-            return new String(encoded);
-        }
-        catch (Exception ex)
-        {
-            throw new RuntimeException(ex);
-        }
-        finally
-        {
-            InternalUtils.close(stream);
-        }
+        return null;
     }
 
-    private void digestStream(MessageDigest digest, InputStream stream) throws IOException
-    {
-        byte[] buffer = new byte[BUFFER_SIZE];
-
-        while (true)
-        {
-            int length = stream.read(buffer);
 
-            if (length < 0) return;
-
-            digest.update(buffer, 0, length);
-        }
-    }
-
-    /**
-     * Current implementation is based on the path extension, and a configured list of extensions.
-     */
     public boolean requiresDigest(String path)
     {
-        int dotx = path.lastIndexOf('.');
-        String extension = path.substring(dotx + 1).toLowerCase();
-
-        return digestExtensions.contains(extension);
+        return false;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestManager.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestManager.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestManager.java
index b3f221d..90b1eb2 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestManager.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestManager.java
@@ -25,8 +25,14 @@ import org.apache.tapestry5.services.ResourceDigestGenerator;
  * <p/>
  * Note that the name and role of this class changed (and diminished) quite a bit in Tapestry 5.3. It is now focused on
  * determining which files require a digest, and which what the digests are for resources.
+ * <p/>
+ * Further, in 5.4, this service has been stripped down to an unused placeholder; it only present to prevent
+ * errors where modules have contributed a String extension to protected (even though the service is internal). As of
+ * 5.4, all assets have a built-in checksum in the URL directly (in 5.3 and earlier, the URL included the application
+ * version number).
  *
  * @deprecated Deprecated in 5.4 with no replacement; see release notes about classpath assets moving to /META-INF/assets/.
+ *             To be removed in 5.5.
  */
 public interface ResourceDigestManager extends InvalidationEventHub
 {
@@ -34,6 +40,8 @@ public interface ResourceDigestManager extends InvalidationEventHub
      * Returns true if the path requires that the client URL for the resource include a digest to validate that the
      * client is authorized to access the resource.
      *
+     * As of 5.4, simply returns false.
+     *
      * @param resource
      * @return true if digest is required for the resource
      * @see ResourceDigestGenerator#requiresDigest(String)
@@ -42,6 +50,8 @@ public interface ResourceDigestManager extends InvalidationEventHub
 
     /**
      * Returns the digest for the given path.
+     * <p/>
+     * As of 5.4, simple returns null.
      *
      * @param resource
      * @return the digest, or null if the resource does not exist

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestManagerImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestManagerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestManagerImpl.java
index a5ee8b1..6812d9d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestManagerImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceDigestManagerImpl.java
@@ -14,99 +14,32 @@
 
 package org.apache.tapestry5.internal.services;
 
-import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
 import org.apache.tapestry5.ioc.Resource;
-import org.apache.tapestry5.ioc.annotations.PostInjection;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.services.InvalidationListener;
-import org.apache.tapestry5.services.ResourceDigestGenerator;
 
-import java.net.URL;
 import java.util.Map;
 
 public class ResourceDigestManagerImpl implements ResourceDigestManager
 {
-    private final ResourceDigestGenerator digestGenerator;
-
-    private final ResourceChangeTracker resourceChangeTracker;
-
-    private final Map<Resource, Cached> cache = CollectionFactory.newConcurrentMap();
-
-    final static long MISSING_RESOURCE_TIME_MODIFIED = -1L;
-
-    private class Cached
-    {
-        final boolean requiresDigest;
-
-        final String digest;
-
-        final long timeModified;
-
-        Cached(Resource resource)
-        {
-            requiresDigest = digestGenerator.requiresDigest(resource.getPath());
-
-            URL url = resource.toURL();
-
-            digest = (requiresDigest && url != null) ? digestGenerator.generateDigest(url) : null;
-
-            timeModified = url != null ? resourceChangeTracker.trackResource(resource) : MISSING_RESOURCE_TIME_MODIFIED;
-        }
-    }
-
-    public ResourceDigestManagerImpl(ResourceDigestGenerator digestGenerator,
-                                     ResourceChangeTracker resourceChangeTracker)
-    {
-        this.digestGenerator = digestGenerator;
-        this.resourceChangeTracker = resourceChangeTracker;
-    }
-
-    @PostInjection
-    public void listenForInvalidations()
-    {
-        resourceChangeTracker.clearOnInvalidation(cache);
-    }
-
-    private Cached get(Resource resource)
-    {
-        Cached result = cache.get(resource);
-
-        if (result == null)
-        {
-            result = new Cached(resource);
-            cache.put(resource, result);
-        }
-
-        return result;
-    }
-
     public String getDigest(Resource resource)
     {
-        return get(resource).digest;
-    }
-
-    public long getTimeModified(Resource resource)
-    {
-        return get(resource).timeModified;
+        return null;
     }
 
     public boolean requiresDigest(Resource resource)
     {
-        return get(resource).requiresDigest;
+        return false;
     }
 
     public void addInvalidationListener(InvalidationListener listener)
     {
-        resourceChangeTracker.addInvalidationListener(listener);
     }
 
     public void addInvalidationCallback(Runnable callback)
     {
-        resourceChangeTracker.addInvalidationCallback(callback);
     }
 
     public void clearOnInvalidation(Map<?, ?> map)
     {
-        resourceChangeTracker.clearOnInvalidation(map);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java
index d1c3656..0a7e39a 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java
@@ -14,8 +14,9 @@
 
 package org.apache.tapestry5.internal.services.assets;
 
-import org.apache.tapestry5.internal.services.AssetResourceLocator;
 import org.apache.tapestry5.internal.services.ResourceStreamer;
+import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.services.AssetSource;
 import org.apache.tapestry5.services.ClasspathAssetAliasManager;
 import org.apache.tapestry5.services.Request;
 import org.apache.tapestry5.services.Response;
@@ -34,18 +35,18 @@ public class ClasspathAssetRequestHandler implements AssetRequestHandler
 {
     private final ResourceStreamer streamer;
 
-    private final AssetResourceLocator assetResourceLocator;
-
     private final AssetChecksumGenerator checksumGenerator;
 
+    private final AssetSource assetSource;
+
     private final String baseFolder;
 
-    public ClasspathAssetRequestHandler(ResourceStreamer streamer, AssetResourceLocator assetResourceLocator,
-                                        AssetChecksumGenerator checksumGenerator, String baseFolder)
+    public ClasspathAssetRequestHandler(ResourceStreamer streamer,
+                                        AssetChecksumGenerator checksumGenerator, AssetSource assetSource, String baseFolder)
     {
         this.streamer = streamer;
-        this.assetResourceLocator = assetResourceLocator;
         this.checksumGenerator = checksumGenerator;
+        this.assetSource = assetSource;
         this.baseFolder = baseFolder;
     }
 
@@ -53,6 +54,8 @@ public class ClasspathAssetRequestHandler implements AssetRequestHandler
     {
         ChecksumPath path = new ChecksumPath(streamer, checksumGenerator, baseFolder, extraPath);
 
-        return path.stream(assetResourceLocator.findClasspathResourceForPath(path.resourcePath));
+        Resource resource = assetSource.resourceForPath(path.resourcePath);
+
+        return path.stream(resource);
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/services/ResourceDigestGenerator.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/ResourceDigestGenerator.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/ResourceDigestGenerator.java
index fb7a618..c1f1477 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/ResourceDigestGenerator.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/ResourceDigestGenerator.java
@@ -22,13 +22,16 @@ import java.net.URL;
  * Responsible for determining which classpath resources require checksums, and for generating checksums for such
  * resources.
  * <p/>
- * The service's configuration identifies which file extensions will be secured using an checksum. The default list is
- * "class" and "tml".
+ * The service's configuration identifies which file extensions will be secured using an checksum. The default list
+ * (in Tapestry 5.3) is
+ * "class" and "tml". Note that in 5.4, there are no longer any contributions to this service by Tapestry, and
+ * that the service is not normally instantiated: it is maintained for backwards compatibility, in case
+ * applications or third-party modules make a contribution.
  *
  * @see org.apache.tapestry5.ioc.internal.util.ClasspathResource
  * @see org.apache.tapestry5.internal.services.ClasspathAssetFactory
  * @deprecated Deprecated in 5.4 with no replacement; see release notes about classpath assets moving
- *             to /META-INF/assets/.
+ *             to /META-INF/assets/, and content checksums inside asset URLs
  */
 @UsesConfiguration(String.class)
 public interface ResourceDigestGenerator
@@ -36,6 +39,8 @@ public interface ResourceDigestGenerator
     /**
      * Examines the path (typically, the file name extension at the end of the path) to determine if a checksum is
      * required for the path. The path is {@link org.apache.tapestry5.ioc.Resource} style, without a leading slash.
+     * <p/>
+     * As of Tapestry 5.4, simply returns false.
      */
     boolean requiresDigest(String path);
 
@@ -44,6 +49,8 @@ public interface ResourceDigestGenerator
      * This digest will be incorporated into the URL provided to the client, to verify that the client has been
      * "granted" access to this resource. This is only used for resources where {@link #requiresDigest(String)} is
      * true.
+     * <p/>
+     * As of Tapestry 5.4, simply returns null.
      *
      * @param url
      * @return the digest for the resource

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
index 786f61d..c5f5e70 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
@@ -312,7 +312,7 @@ public final class TapestryModule
         binder.bind(Cookies.class, CookiesImpl.class);
         binder.bind(FieldValidatorDefaultSource.class, FieldValidatorDefaultSourceImpl.class);
         binder.bind(RequestGlobals.class, RequestGlobalsImpl.class);
-        binder.bind(ResourceDigestGenerator.class, ResourceDigestGeneratorImpl.class);
+        binder.bind(ResourceDigestGenerator.class, ResourceDigestGeneratorImpl.class);  // Remove in 5.5
         binder.bind(ValidationConstraintGenerator.class, ValidationConstraintGeneratorImpl.class);
         binder.bind(EnvironmentalShadowBuilder.class, EnvironmentalShadowBuilderImpl.class);
         binder.bind(ComponentSource.class, ComponentSourceImpl.class);
@@ -1948,33 +1948,6 @@ public final class TapestryModule
         configuration.add("Secure", secureFilter);
     }
 
-    /**
-     * Configures the extensions that will require a digest to be downloaded via
-     * the asset dispatcher. Most resources
-     * are "safe", they don't require a digest. For unsafe resources, the digest
-     * is incorporated into the URL to ensure
-     * that the client side isn't just "fishing".
-     * <p/>
-     * The extensions must be all lower case.
-     * <p/>
-     * This contributes "class", "properties" and "tml" (the template extension).
-     *
-     * @param configuration
-     *         collection of extensions
-     */
-    public static void contributeResourceDigestGenerator(Configuration<String> configuration)
-    {
-        // Java class files always require a digest.
-        configuration.add("class");
-
-        // Even though properties don't contain sensible data we should protect
-        // them.
-        configuration.add("properties");
-
-        // Likewise, we don't want people fishing for templates.
-        configuration.add(TapestryConstants.TEMPLATE_EXTENSION);
-    }
-
     public static void contributeTemplateParser(MappedConfiguration<String, URL> config)
     {
         // Any class inside the internal module would do. Or we could move all

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/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 0955427..efb21a3 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
@@ -222,8 +222,9 @@ public class AssetsModule
 
                                                       AssetChecksumGenerator assetChecksumGenerator,
 
-                                                      ClasspathAssetAliasManager classpathAssetAliasManager, ResourceStreamer streamer,
-                                                      AssetResourceLocator assetResourceLocator)
+                                                      ClasspathAssetAliasManager classpathAssetAliasManager,
+                                                      ResourceStreamer streamer,
+                                                      AssetSource assetSource)
     {
         Map<String, String> mappings = classpathAssetAliasManager.getMappings();
 
@@ -231,7 +232,7 @@ public class AssetsModule
         {
             String path = mappings.get(folder);
 
-            configuration.add(folder, new ClasspathAssetRequestHandler(streamer, assetResourceLocator, assetChecksumGenerator, path));
+            configuration.add(folder, new ClasspathAssetRequestHandler(streamer, assetChecksumGenerator, assetSource, path));
         }
 
         configuration.add(RequestConstants.CONTEXT_FOLDER,

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java b/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java
index 786b25b..143b40f 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/test/TapestryTestCase.java
@@ -253,11 +253,6 @@ public abstract class TapestryTestCase extends IOCTestCase
         return newMock(RequestHandler.class);
     }
 
-    protected final ResourceDigestGenerator mockResourceDigestGenerator()
-    {
-        return newMock(ResourceDigestGenerator.class);
-    }
-
     protected final Response mockResponse()
     {
         return newMock(Response.class);
@@ -618,11 +613,6 @@ public abstract class TapestryTestCase extends IOCTestCase
         setAnswer(answer);
     }
 
-    protected final void train_requiresDigest(ResourceDigestGenerator generator, String path, boolean requiresDigest)
-    {
-        expect(generator.requiresDigest(path)).andReturn(requiresDigest);
-    }
-
     protected final void train_service(RequestHandler handler, Request request, Response response, boolean result)
             throws IOException
     {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/test/app1/AssetProtectionDemo.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/app1/AssetProtectionDemo.tml b/tapestry-core/src/test/app1/AssetProtectionDemo.tml
index bee9c10..e5e99db 100644
--- a/tapestry-core/src/test/app1/AssetProtectionDemo.tml
+++ b/tapestry-core/src/test/app1/AssetProtectionDemo.tml
@@ -1,13 +1,21 @@
 <html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
-    <a href="${asset:context:availablefile.txt}">Available File</a>
-    <a href="${asset:context:WEB-INF/unavailable.css}">Unavailable CSS</a>
-    <a href="${asset:context:WEB-INF}">WEB-INF</a>
-    <a href="${asset:context:WEB-INF/}">WEB-INF/</a>
-    <a href="${asset:classpath:/org/apache/tapestry5/integration/app1/pages/unavailablefile.txt}">Unavailable File</a>
-    <a href="${asset:classpath:/org/apache/tapestry5/integration/app1/pages/availablefile2.txt}">Available File2</a>
-    <a href="${asset:context:META-INF}">META-INF</a>
-    <a href="${asset:context:META-INF/}">META-INF/</a>
-    <a href="${asset:context:META-INF/unavailable2.txt}">unavailable2.txt</a>
-    <a href="${asset:context:AssetProtectionDemo.tml}">tml file</a>
-    <a href="${asset:context:music/MusicDetails.tml}">nested tml file</a>
+
+<h1>Asset Protection Demo</h1>
+
+<ul>
+    <li><a href="${asset:context:availablefile.txt}">Available File</a></li>
+    <li><a href="${asset:context:WEB-INF/unavailable.css}">Unavailable CSS</a></li>
+    <li><a href="${asset:context:WEB-INF}">WEB-INF</a></li>
+    <li><a href="${asset:context:WEB-INF/}">WEB-INF/</a></li>
+    <li><a href="${asset:classpath:/org/apache/tapestry5/integration/app1/pages/unavailablefile.txt}">Unavailable
+        File</a></li>
+    <li><a href="${asset:classpath:/org/apache/tapestry5/integration/app1/pages/availablefile2.txt}">Available File2</a>
+    </li>
+    <li><a href="${asset:context:META-INF}">META-INF</a></li>
+    <li><a href="${asset:context:META-INF/}">META-INF/</a></li>
+    <li><a href="${asset:context:META-INF/unavailable2.txt}">unavailable2.txt</a></li>
+    <li><a href="${asset:context:AssetProtectionDemo.tml}">tml file</a></li>
+    <li><a href="${asset:context:music/MusicDetails.tml}">nested tml file</a></li>
+</ul>
+
 </html>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AssetDigestTests.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AssetDigestTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AssetDigestTests.groovy
deleted file mode 100644
index 0d5d9e0..0000000
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AssetDigestTests.groovy
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2011 The Apache Software Foundation
-//
-// Licensed 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 org.apache.tapestry5.integration.app1
-
-import org.apache.tapestry5.integration.TapestryCoreTestCase
-import org.testng.annotations.Test
-
-/**
- * Tests access to a "protected" asset, one that requires a digest in the URL in order to access.  Ensures
- * that such assets can only be accessed using a URL with the necessary digest.
- */
-class AssetDigestTests extends TapestryCoreTestCase
-{
-    def tryBadPath(badPath) {
-        def url = new URL("${baseURL}${badPath}")
-
-        try {
-            url.getText()
-            unreachable()
-        }
-        catch (IOException ex) {
-            assert ex.getMessage().contains("403")
-        }
-    }
-
-    @Test
-    void protected_asset() {
-        openLinks "AssetDemo"
-
-        def path = getText("propurl").substring(1) // Strip leading slash
-
-        def url = new URL("${baseURL}${path}")
-
-        def p = new Properties();
-
-        p.load(url.newInputStream())
-
-        printf("URL: %s\nProperties: %s\n",  url, p)
-
-        assert p.getProperty("note") == "Should be protected via a MD5 checksum"
-
-        assert path ==~ /.*\/AssetDemo\.\p{XDigit}+\.properties/
-    }
-
-    @Test
-    void invalid_digest() {
-        openLinks "AssetDemo"
-
-        def path = getText("propurl").substring(1)
-
-        tryBadPath ((path =~ /\.\p{XDigit}+\.properties/).replaceFirst(".abc.properties"))
-    }
-
-
-    @Test
-    void missing_digest() {
-        openLinks "AssetDemo"
-
-        def path = getText("propurl").substring(1)
-
-        tryBadPath( (path =~ /\.\p{XDigit}+\.properties/).replaceFirst(".properties"))
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
index bb54e4c..7a2c812 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
@@ -281,6 +281,7 @@ public class AppModule
         configuration.add("PreApp", preappResource, "before:AppCatalog");
     }
 
+    // Remove this in 5.5:
     @Contribute(ResourceDigestGenerator.class)
     public static void protectPropertiesFiles(Configuration<String> configuration)
     {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java
index 4a393a2..bdddceb 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java
@@ -29,21 +29,17 @@ public class ClasspathAssetFactoryTest extends InternalBaseTestCase
     @Test
     public void asset_client_URL_is_cached()
     {
-        ResourceDigestManager digestManager = mockResourceResourceDigestManager();
-
         Resource r = new ClasspathResource("foo/Bar.txt");
 
         ClasspathAssetAliasManager aliasManager = mockClasspathAssetAliasManager();
 
-        train_requiresDigest(digestManager, r, false);
-
         String expectedClientURL = "/context/asset/foo/Bar.txt";
 
         expect(aliasManager.toClientURL(r)).andReturn(expectedClientURL);
 
         replay();
 
-        ClasspathAssetFactory factory = new ClasspathAssetFactory(digestManager, aliasManager, converter);
+        ClasspathAssetFactory factory = new ClasspathAssetFactory(aliasManager, converter);
 
         Asset asset = factory.createAsset(r);
 
@@ -59,20 +55,17 @@ public class ClasspathAssetFactoryTest extends InternalBaseTestCase
     @Test
     public void simple_asset_client_URL()
     {
-        ResourceDigestManager digestManager = mockResourceResourceDigestManager();
         ClasspathAssetAliasManager aliasManager = mockClasspathAssetAliasManager();
 
         Resource r = new ClasspathResource("foo/Bar.txt");
 
-        train_requiresDigest(digestManager, r, false);
-
         String expectedClientURL = "/context/asset/foo/Bar.txt";
 
         expect(aliasManager.toClientURL(r)).andReturn(expectedClientURL);
 
         replay();
 
-        AssetFactory factory = new ClasspathAssetFactory(digestManager, aliasManager, new IdentityAssetPathConverter());
+        AssetFactory factory = new ClasspathAssetFactory(aliasManager, new IdentityAssetPathConverter());
 
         Asset asset = factory.createAsset(r);
 
@@ -82,34 +75,4 @@ public class ClasspathAssetFactoryTest extends InternalBaseTestCase
 
         verify();
     }
-
-    @Test
-    public void protected_asset_client_URL()
-    {
-        ResourceDigestManager digestManager = mockResourceResourceDigestManager();
-        ClasspathAssetAliasManager aliasManager = mockClasspathAssetAliasManager();
-
-        Resource r = new ClasspathResource("foo/Bar.txt");
-
-        train_requiresDigest(digestManager, r, true);
-
-        expect(digestManager.getDigest(r)).andReturn("ABC123");
-
-        String expectedClientURL = "/context/asset/foo/Bar.ABC123.txt";
-
-        expect(aliasManager.toClientURL(r)).andReturn(expectedClientURL);
-
-        replay();
-
-        AssetFactory factory = new ClasspathAssetFactory(digestManager, aliasManager, new IdentityAssetPathConverter());
-
-        Asset asset = factory.createAsset(r);
-
-        assertSame(asset.getResource(), r);
-        assertEquals(asset.toClientURL(), expectedClientURL);
-        assertEquals(asset.toString(), expectedClientURL);
-
-        verify();
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResourceDigestGeneratorImplTest.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResourceDigestGeneratorImplTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResourceDigestGeneratorImplTest.java
deleted file mode 100644
index f739004..0000000
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResourceDigestGeneratorImplTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2006 The Apache Software Foundation
-//
-// Licensed 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 org.apache.tapestry5.internal.services;
-
-import org.apache.tapestry5.internal.test.InternalBaseTestCase;
-import org.apache.tapestry5.services.ResourceDigestGenerator;
-import org.testng.annotations.Test;
-
-import java.io.*;
-import java.net.URL;
-import java.util.Arrays;
-
-public class ResourceDigestGeneratorImplTest extends InternalBaseTestCase
-{
-    @Test
-    public void typical_file() throws Exception
-    {
-        URL url = getClass().getResource("ResourceDigestGeneratorImplTest.class");
-
-        ResourceDigestGenerator g = new ResourceDigestGeneratorImpl(Arrays.asList("class"));
-
-        String digest = g.generateDigest(url);
-
-        assertTrue(digest.length() > 0);
-
-        String checksum2 = g.generateDigest(url);
-
-        assertEquals(checksum2, digest);
-    }
-
-    @Test
-    public void digest_changes_with_changes_to_file() throws Exception
-    {
-        File file = File.createTempFile("digest.", ".dat");
-
-        URL url = file.toURL();
-
-        ResourceDigestGenerator g = new ResourceDigestGeneratorImpl(Arrays.asList("class"));
-
-        String prevDigest = g.generateDigest(url);
-
-        for (int i = 0; i < 5; i++)
-        {
-            writeJunkTofile(file);
-
-            String digest = g.generateDigest(url);
-
-            assertFalse(digest.equals(prevDigest));
-
-            prevDigest = digest;
-
-        }
-    }
-
-    private void writeJunkTofile(File file) throws IOException
-    {
-        OutputStream os = new BufferedOutputStream(new FileOutputStream(file, true));
-
-        OutputStreamWriter writer = new OutputStreamWriter(os);
-
-        for (int i = 0; i < 1000; i++)
-            writer.write("All work and no play makes Jack a dull boy. ");
-
-        writer.close();
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResourceDigestManagerTest.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResourceDigestManagerTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResourceDigestManagerTest.java
deleted file mode 100644
index 1798e08..0000000
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResourceDigestManagerTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright 2006, 2007, 2008, 2011 The Apache Software Foundation
-//
-// Licensed 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 org.apache.tapestry5.internal.services;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-
-import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
-import org.apache.tapestry5.internal.test.InternalBaseTestCase;
-import org.apache.tapestry5.ioc.Resource;
-import org.apache.tapestry5.services.InvalidationListener;
-import org.apache.tapestry5.services.ResourceDigestGenerator;
-import org.apache.tapestry5.services.UpdateListenerHub;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-public class ResourceDigestManagerTest extends InternalBaseTestCase
-{
-    private static final String PATH = "foo/Bar.gif";
-
-    private static final String DIGEST = "abc123";
-
-    private ResourceChangeTracker resourceChangeTracker;
-
-    @BeforeClass
-    public void setup()
-    {
-        resourceChangeTracker = getService(ResourceChangeTracker.class);
-    }
-
-    @AfterClass
-    public void cleanup()
-    {
-        resourceChangeTracker = null;
-    }
-
-    @Test
-    public void properties_for_simple_resource() throws Exception
-    {
-        ResourceDigestGenerator generator = mockResourceDigestGenerator();
-
-        File f = createTestFile();
-        URL url = f.toURL();
-        Resource r = mockResource();
-
-        long lastUpdated = f.lastModified();
-        lastUpdated -= lastUpdated % 1000;
-
-        train_getPath(r, PATH);
-        train_toURL(r, url);
-
-        train_requiresDigest(generator, PATH, false);
-
-        replay();
-
-        ResourceDigestManagerImpl cache = new ResourceDigestManagerImpl(generator, resourceChangeTracker);
-
-        assertEquals(cache.requiresDigest(r), false);
-        assertEquals(cache.getTimeModified(r), lastUpdated);
-        assertEquals(cache.getDigest(r), null);
-
-        verify();
-    }
-
-    @Test
-    public void properties_for_missing_resource() throws Exception
-    {
-        ResourceDigestGenerator generator = mockResourceDigestGenerator();
-
-        Resource r = mockResource();
-
-        train_getPath(r, PATH);
-        train_toURL(r, null);
-
-        train_requiresDigest(generator, PATH, true);
-
-        replay();
-
-        ResourceDigestManagerImpl cache = new ResourceDigestManagerImpl(generator, null);
-
-        assertEquals(cache.requiresDigest(r), true);
-        assertEquals(cache.getTimeModified(r), ResourceDigestManagerImpl.MISSING_RESOURCE_TIME_MODIFIED);
-        assertEquals(cache.getDigest(r), null);
-
-        verify();
-    }
-
-    @Test
-    public void properties_for_protected_resource() throws Exception
-    {
-        ResourceDigestGenerator generator = mockResourceDigestGenerator();
-
-        File f = createTestFile();
-        URL url = f.toURL();
-        Resource r = mockResource();
-
-        long lastUpdated = f.lastModified();
-        lastUpdated -= lastUpdated % 1000;
-
-        train_getPath(r, PATH);
-        train_toURL(r, url);
-
-        train_requiresDigest(generator, PATH, true);
-        train_generateChecksum(generator, url, DIGEST);
-
-        replay();
-
-        ResourceDigestManagerImpl cache = new ResourceDigestManagerImpl(generator, resourceChangeTracker);
-
-        assertEquals(cache.requiresDigest(r), true);
-        assertEquals(cache.getTimeModified(r), lastUpdated);
-        assertEquals(cache.getDigest(r), DIGEST);
-
-        verify();
-    }
-
-    @Test
-    public void caching_and_invalidation() throws Exception
-    {
-        // Alas, mixing and matching live code with mocks
-        ResourceDigestGenerator generator = mockResourceDigestGenerator();
-        InvalidationListener listener = mockInvalidationListener();
-        File f = createTestFile();
-        URL url = f.toURL();
-        Resource r = mockResource();
-
-        long lastUpdated = f.lastModified();
-        lastUpdated -= lastUpdated % 1000;
-
-        train_getPath(r, PATH);
-        train_toURL(r, url);
-
-        train_requiresDigest(generator, PATH, true);
-        train_generateChecksum(generator, url, DIGEST);
-
-        replay();
-
-        ResourceDigestManagerImpl cache = new ResourceDigestManagerImpl(generator, resourceChangeTracker);
-        cache.listenForInvalidations();
-        cache.addInvalidationListener(listener);
-
-        assertEquals(cache.requiresDigest(r), true);
-        assertEquals(cache.getTimeModified(r), lastUpdated);
-        assertEquals(cache.getDigest(r), DIGEST);
-
-        // No updates yet
-        getService(UpdateListenerHub.class).fireCheckForUpdates();
-
-        verify();
-
-        Thread.sleep(1500);
-        touch(f);
-
-        lastUpdated = f.lastModified();
-        lastUpdated -= lastUpdated % 1000;
-
-        String expectedDigest = "FREDBARNEY";
-
-        train_getPath(r, PATH);
-        train_toURL(r, url);
-        train_requiresDigest(generator, PATH, true);
-        train_generateChecksum(generator, url, expectedDigest);
-
-        listener.objectWasInvalidated();
-
-        replay();
-
-        getService(UpdateListenerHub.class).fireCheckForUpdates();
-
-        assertEquals(cache.requiresDigest(r), true);
-        assertEquals(cache.getTimeModified(r), lastUpdated);
-        assertEquals(cache.getDigest(r), expectedDigest);
-
-        verify();
-    }
-
-    private File createTestFile() throws IOException
-    {
-        return File.createTempFile("ResourceCacheImplTest.", ".tst");
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/b3428cc3/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
index 5882544..62b0fcf 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
@@ -233,16 +233,6 @@ public class InternalBaseTestCase extends TapestryTestCase implements Registry
         expect(page.getRootComponent()).andReturn(component).atLeastOnce();
     }
 
-    protected final ResourceDigestManager mockResourceResourceDigestManager()
-    {
-        return newMock(ResourceDigestManager.class);
-    }
-
-    protected final void train_requiresDigest(ResourceDigestManager manager, Resource resource, boolean requiresChecksum)
-    {
-        expect(manager.requiresDigest(resource)).andReturn(requiresChecksum);
-    }
-
     protected final InvalidationListener mockInvalidationListener()
     {
         return newMock(InvalidationListener.class);