WICKET-5446 Improve version matching in resource caching strategies
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/2bd971ad Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/2bd971ad Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/2bd971ad Branch: refs/heads/sandbox/WICKET-4686 Commit: 2bd971ad723cd9ad2c10d868149d677dcb6abab3 Parents: a535cd3 Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Tue Dec 17 11:18:02 2013 +0200 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Tue Dec 17 11:19:05 2013 +0200 ---------------------------------------------------------------------- ...enameWithVersionResourceCachingStrategy.java | 24 +++++++++---- .../caching/version/CachingResourceVersion.java | 6 ++++ .../caching/version/IResourceVersion.java | 10 ++++++ .../version/LastModifiedResourceVersion.java | 13 +++++++ .../version/MessageDigestResourceVersion.java | 12 +++++++ .../RequestCycleCachedResourceVersion.java | 7 ++++ .../caching/version/StaticResourceVersion.java | 10 ++++++ .../BasicResourceReferenceMapperTest.java | 38 +++++++++++++++++++- .../ContextRelativeResourceCachingTest.java | 2 +- ...eWithVersionResourceCachingStrategyTest.java | 18 ++++++++++ 10 files changed, 131 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/2bd971ad/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategy.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategy.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategy.java index 087ea13..0afd86c 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategy.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategy.java @@ -16,6 +16,8 @@ */ package org.apache.wicket.request.resource.caching; +import java.util.regex.Pattern; + import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.request.http.WebResponse; import org.apache.wicket.request.resource.AbstractResource; @@ -110,12 +112,6 @@ public class FilenameWithVersionResourceCachingStrategy implements IResourceCach // get undecorated filename final String filename = url.getFileName(); - if (filename.contains(getVersionPrefix())) - { - LOG.error("A resource with name '{}' contains the version prefix '{}' so the un-decoration will not work." + - " Either use a different version prefix or rename this resource.", filename, getVersionPrefix()); - } - // check if resource name has extension final int extensionAt = filename.lastIndexOf('.'); @@ -135,6 +131,14 @@ public class FilenameWithVersionResourceCachingStrategy implements IResourceCach { versionedFilename.append(filename.substring(0, extensionAt)); } + + int pos = versionedFilename.indexOf(getVersionPrefix()); + if (pos != -1 && isVersion(versionedFilename.substring(pos + versionPrefix.length()))) + { + LOG.error("A resource with name '{}' contains the version prefix '{}' so the un-decoration will not work." + + " Either use a different version prefix or rename this resource.", filename, getVersionPrefix()); + } + // add version suffix versionedFilename.append(versionPrefix); @@ -168,7 +172,7 @@ public class FilenameWithVersionResourceCachingStrategy implements IResourceCach pos = fullname.lastIndexOf(versionPrefix); // remove version string if it exists - if (pos != -1) + if (pos != -1 && isVersion(fullname.substring(pos + versionPrefix.length()))) { // get filename before version string final String basename = fullname.substring(0, pos); @@ -188,6 +192,12 @@ public class FilenameWithVersionResourceCachingStrategy implements IResourceCach } } + private boolean isVersion(String substring) + { + Pattern versionPattern = resourceVersion.getVersionPattern(); + return versionPattern == null || versionPattern.matcher(substring).matches(); + } + /** * set resource caching to maximum and set cache-visibility to 'public' * http://git-wip-us.apache.org/repos/asf/wicket/blob/2bd971ad/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/CachingResourceVersion.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/CachingResourceVersion.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/CachingResourceVersion.java index f237446..a2639a1 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/CachingResourceVersion.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/CachingResourceVersion.java @@ -19,6 +19,7 @@ package org.apache.wicket.request.resource.caching.version; import java.io.Serializable; import java.util.Collections; import java.util.Map; +import java.util.regex.Pattern; import org.apache.wicket.request.resource.caching.IStaticCacheableResource; import org.apache.wicket.util.collections.MostRecentlyUsedMap; @@ -134,6 +135,11 @@ public class CachingResourceVersion implements IResourceVersion return version; } + @Override + public Pattern getVersionPattern() { + return delegate.getVersionPattern(); + } + /** * remove cacheable resource from cache * http://git-wip-us.apache.org/repos/asf/wicket/blob/2bd971ad/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/IResourceVersion.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/IResourceVersion.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/IResourceVersion.java index e4b92d1..f24124b 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/IResourceVersion.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/IResourceVersion.java @@ -16,6 +16,8 @@ */ package org.apache.wicket.request.resource.caching.version; +import java.util.regex.Pattern; + import org.apache.wicket.request.resource.caching.IStaticCacheableResource; /** @@ -41,4 +43,12 @@ public interface IResourceVersion * if version string could not be calculated */ String getVersion(IStaticCacheableResource resource); + + /** + * a pattern that matches returned versions + * + * @return a pattern or <code>null</code> if no pattern + * is available + */ + Pattern getVersionPattern(); } http://git-wip-us.apache.org/repos/asf/wicket/blob/2bd971ad/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/LastModifiedResourceVersion.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/LastModifiedResourceVersion.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/LastModifiedResourceVersion.java index d01a573..dcdbc6c 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/LastModifiedResourceVersion.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/LastModifiedResourceVersion.java @@ -16,6 +16,8 @@ */ package org.apache.wicket.request.resource.caching.version; +import java.util.regex.Pattern; + import org.apache.wicket.request.resource.caching.IStaticCacheableResource; import org.apache.wicket.util.resource.IResourceStream; import org.apache.wicket.util.time.Time; @@ -30,6 +32,11 @@ import org.apache.wicket.util.time.Time; */ public class LastModifiedResourceVersion implements IResourceVersion { + /** + * A valid pattern is a sequence of digits + */ + private static final Pattern TIMESTAMP_PATTERN = Pattern.compile("[0-9]+"); + @Override public String getVersion(IStaticCacheableResource resource) { @@ -52,4 +59,10 @@ public class LastModifiedResourceVersion implements IResourceVersion // version string = last modified timestamp converted to milliseconds return String.valueOf(lastModified.getMilliseconds()); } + + @Override + public Pattern getVersionPattern() + { + return TIMESTAMP_PATTERN; + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/2bd971ad/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/MessageDigestResourceVersion.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/MessageDigestResourceVersion.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/MessageDigestResourceVersion.java index a320fd6..9652e05 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/MessageDigestResourceVersion.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/MessageDigestResourceVersion.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.regex.Pattern; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.request.resource.caching.IStaticCacheableResource; @@ -53,6 +54,11 @@ public class MessageDigestResourceVersion implements IResourceVersion private static final int DEFAULT_BUFFER_BYTES = 8192; // needed for javadoc {@value ..} private static final Bytes DEFAULT_BUFFER_SIZE = Bytes.bytes(DEFAULT_BUFFER_BYTES); + /** + * A valid pattern is a sequence of digits and upper cased English letters A-F + */ + private static final Pattern DIGEST_PATTERN = Pattern.compile("[0-9A-F]+"); + /** * message digest algorithm for computing hashes */ @@ -153,6 +159,12 @@ public class MessageDigestResourceVersion implements IResourceVersion } } + @Override + public Pattern getVersionPattern() + { + return DIGEST_PATTERN; + } + /** * get instance of message digest provider from JCA * http://git-wip-us.apache.org/repos/asf/wicket/blob/2bd971ad/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/RequestCycleCachedResourceVersion.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/RequestCycleCachedResourceVersion.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/RequestCycleCachedResourceVersion.java index dbcec9d..e726858 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/RequestCycleCachedResourceVersion.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/RequestCycleCachedResourceVersion.java @@ -18,6 +18,7 @@ package org.apache.wicket.request.resource.caching.version; import java.io.Serializable; import java.util.Map; +import java.util.regex.Pattern; import org.apache.wicket.MetaDataKey; import org.apache.wicket.ThreadContext; @@ -104,4 +105,10 @@ public class RequestCycleCachedResourceVersion implements IResourceVersion return version; } + + @Override + public Pattern getVersionPattern() + { + return delegate.getVersionPattern(); + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/2bd971ad/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/StaticResourceVersion.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/StaticResourceVersion.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/StaticResourceVersion.java index cefc700..5d4b941 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/StaticResourceVersion.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/StaticResourceVersion.java @@ -16,6 +16,8 @@ */ package org.apache.wicket.request.resource.caching.version; +import java.util.regex.Pattern; + import org.apache.wicket.request.resource.caching.IStaticCacheableResource; import org.apache.wicket.util.lang.Args; @@ -29,6 +31,7 @@ import org.apache.wicket.util.lang.Args; public class StaticResourceVersion implements IResourceVersion { private final String version; + private final Pattern pattern; /** * create static version provider @@ -39,6 +42,7 @@ public class StaticResourceVersion implements IResourceVersion public StaticResourceVersion(String version) { this.version = Args.notNull(version, "version"); + this.pattern = Pattern.compile(Pattern.quote(version)); } @Override @@ -46,4 +50,10 @@ public class StaticResourceVersion implements IResourceVersion { return version; } + + @Override + public Pattern getVersionPattern() + { + return pattern; + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/2bd971ad/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/BasicResourceReferenceMapperTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/BasicResourceReferenceMapperTest.java b/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/BasicResourceReferenceMapperTest.java index 3e075e0..d7cce88 100644 --- a/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/BasicResourceReferenceMapperTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/core/request/mapper/BasicResourceReferenceMapperTest.java @@ -20,6 +20,7 @@ import static org.hamcrest.CoreMatchers.instanceOf; import java.io.Serializable; import java.util.Locale; +import java.util.regex.Pattern; import org.apache.wicket.request.IRequestHandler; import org.apache.wicket.request.Url; @@ -34,9 +35,11 @@ import org.apache.wicket.request.resource.caching.IResourceCachingStrategy; import org.apache.wicket.request.resource.caching.IStaticCacheableResource; import org.apache.wicket.request.resource.caching.NoOpResourceCachingStrategy; import org.apache.wicket.request.resource.caching.ResourceUrl; +import org.apache.wicket.request.resource.caching.version.IResourceVersion; import org.apache.wicket.request.resource.caching.version.StaticResourceVersion; import org.apache.wicket.util.IProvider; import org.apache.wicket.util.ValueProvider; +import org.apache.wicket.util.lang.Args; import org.apache.wicket.util.resource.IResourceStream; import org.apache.wicket.util.resource.StringResourceStream; import org.junit.Test; @@ -501,7 +504,7 @@ public class BasicResourceReferenceMapperTest extends AbstractResourceReferenceM }; IResourceCachingStrategy strategy = new FilenameWithVersionResourceCachingStrategy( - "-version-", new StaticResourceVersion("foobar")); + "-version-", new AlphaDigitResourceVersion("foobar")); INamedParameters params = new PageParameters(); ResourceUrl url = new ResourceUrl("test.js", params); @@ -550,6 +553,39 @@ public class BasicResourceReferenceMapperTest extends AbstractResourceReferenceM } /** + * A resource version that allows any of: alpha, digit, dash and dot charcters + */ + private static class AlphaDigitResourceVersion implements IResourceVersion + { + private static final Pattern pattern = Pattern.compile("[0-9a-z-\\.]*"); + + private final String version; + + /** + * create static version provider + * + * @param version + * static version string to deliver for all queries resources + */ + public AlphaDigitResourceVersion(String version) + { + this.version = Args.notNull(version, "version"); + } + + @Override + public String getVersion(IStaticCacheableResource resource) + { + return version; + } + + @Override + public Pattern getVersionPattern() + { + return pattern; + } + } + + /** * */ @Test http://git-wip-us.apache.org/repos/asf/wicket/blob/2bd971ad/wicket-core/src/test/java/org/apache/wicket/request/resource/caching/ContextRelativeResourceCachingTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/request/resource/caching/ContextRelativeResourceCachingTest.java b/wicket-core/src/test/java/org/apache/wicket/request/resource/caching/ContextRelativeResourceCachingTest.java index 0821a38..3fdd8ee 100644 --- a/wicket-core/src/test/java/org/apache/wicket/request/resource/caching/ContextRelativeResourceCachingTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/request/resource/caching/ContextRelativeResourceCachingTest.java @@ -98,7 +98,7 @@ public class ContextRelativeResourceCachingTest extends WicketTestCase ContextRelativeResource resource = new ContextRelativeResource("/style.css"); init(resource, "/test/resource"); - Request request = createRequest("test/resource-version-4711?bla=123"); + Request request = createRequest("test/resource-version-123?bla=4567"); final IRequestHandler handler = tester.getApplication().getRootRequestMapper() .mapRequest(request); assertThat(handler, instanceOf(ResourceReferenceRequestHandler.class)); http://git-wip-us.apache.org/repos/asf/wicket/blob/2bd971ad/wicket-core/src/test/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategyTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategyTest.java b/wicket-core/src/test/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategyTest.java index 9ad3a7f..0c82205 100644 --- a/wicket-core/src/test/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategyTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategyTest.java @@ -49,6 +49,12 @@ public class FilenameWithVersionResourceCachingStrategyTest extends Assert strategy.decorateUrl(resourceUrl, new TestResource()); assertEquals("some-resource--vers--"+TEST_RESOURCE_VERSION+".txt", resourceUrl.getFileName()); + + // don't issue an error + resourceUrl = new ResourceUrl("some-resource--vers--with-prefix.txt", new PageParameters()); + strategy.decorateUrl(resourceUrl, new TestResource()); + + assertEquals("some-resource--vers--with-prefix--vers--"+TEST_RESOURCE_VERSION+".txt", resourceUrl.getFileName()); } @Test @@ -58,6 +64,18 @@ public class FilenameWithVersionResourceCachingStrategyTest extends Assert strategy.undecorateUrl(resourceUrl); assertEquals("some-resource.txt", resourceUrl.getFileName()); + + // test URL with versiton containing prefix in original + resourceUrl = new ResourceUrl("some-resource--vers--with-prefix--vers--"+TEST_RESOURCE_VERSION+".txt", new PageParameters()); + strategy.undecorateUrl(resourceUrl); + + assertEquals("some-resource--vers--with-prefix.txt", resourceUrl.getFileName()); + + // test URL without version containing prefix + resourceUrl = new ResourceUrl("some-resource--vers--without-version.txt", new PageParameters()); + strategy.undecorateUrl(resourceUrl); + + assertEquals("some-resource--vers--without-version.txt", resourceUrl.getFileName()); } @Test
