Author: pete
Date: Wed Jun 29 22:32:59 2011
New Revision: 1141298
URL: http://svn.apache.org/viewvc?rev=1141298&view=rev
Log:
WICKET-3846 rework resource caching so it will by default work in clusters,
also made the whole caching stuff pluggable and easier to extend
Added:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategy.java
- copied, changed from r1141191,
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/AbstractFilenameWithVersionResourceCachingStrategy.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/QueryStringWithVersionResourceCachingStrategy.java
- copied, changed from r1141191,
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/QueryStringWithTimestampResourceCachingStrategy.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/CachingResourceVersion.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/IResourceVersion.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/LastModifiedResourceVersion.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/MessageDigestResourceVersion.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/RequestCycleCachedResourceVersion.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/StaticResourceVersion.java
Removed:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/AbstractFilenameWithVersionResourceCachingStrategy.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/AbstractResourceCachingStrategy.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithStaticVersionResourceCachingStrategy.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithTimestampResourceCachingStrategy.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/QueryStringWithTimestampResourceCachingStrategy.java
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/IResourceCachingStrategy.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/NoOpResourceCachingStrategy.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/ResourceSettings.java
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/mapper/BasicResourceReferenceMapperTest.java
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java?rev=1141298&r1=1141297&r2=1141298&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java
(original)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java
Wed Jun 29 22:32:59 2011
@@ -304,7 +304,7 @@ public class PackageResource extends Abs
*
* @return resource stream or <code>null</code> if not found
*/
- protected IResourceStream getResourceStream()
+ public IResourceStream getResourceStream()
{
// Locate resource
return ThreadContext.getApplication()
Copied:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategy.java
(from r1141191,
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/AbstractFilenameWithVersionResourceCachingStrategy.java)
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategy.java?p2=wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategy.java&p1=wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/AbstractFilenameWithVersionResourceCachingStrategy.java&r1=1141191&r2=1141298&rev=1141298&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/AbstractFilenameWithVersionResourceCachingStrategy.java
(original)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/FilenameWithVersionResourceCachingStrategy.java
Wed Jun 29 22:32:59 2011
@@ -19,15 +19,17 @@ package org.apache.wicket.request.resour
import org.apache.wicket.request.http.WebResponse;
import org.apache.wicket.request.resource.AbstractResource;
import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.request.resource.caching.version.IResourceVersion;
import org.apache.wicket.util.lang.Args;
/**
- * base resource caching strategy that adds a version string for the
+ * resource caching strategy that adds a version string for the
* requested resource to the filename.
* <p/>
- * versioned_filename := [basename][version-suffix][version](.extension)
+ * versioned_filename := [basename][version-prefix][version](.extension)
* <p/>
- * the <code>version</code> must not contain the <code>version-suffix</code>.
+ * the <code>version</code> must not contain the <code>version-prefix</code> so
+ * please use an unambigous value for the <code>version-prefix</code>.
* <p/>
* Since browsers and proxies use the versioned filename of the resource url
* as a cache key a change to the version will cause a cache miss and
subsequent
@@ -36,39 +38,64 @@ import org.apache.wicket.util.lang.Args;
* <p/>
*
* @author Peter Ertl
+ *
+ * @since 1.5
*/
-public abstract class AbstractFilenameWithVersionResourceCachingStrategy
- extends AbstractResourceCachingStrategy
+public class FilenameWithVersionResourceCachingStrategy implements
IResourceCachingStrategy
{
+ private static final String DEFAULT_VERSION_PREFIX = "-ver-";
+
/**
- * suffix that marks the beginning the of the version
- * string inside the resource filename */
- private final String versionSuffix;
+ * prefix that marks the beginning the of the version
+ * string contained in the decorated resource filename
+ * */
+ private final String versionPrefix;
+
+ /**
+ * resource version provider
+ */
+ private final IResourceVersion resourceVersion;
/**
* Constructor
*
- * @param versionSuffix
- * string appended to the filename before the version string
+ * @param resourceVersion
+ * resource version object
*/
- public AbstractFilenameWithVersionResourceCachingStrategy(String
versionSuffix)
+ public FilenameWithVersionResourceCachingStrategy(IResourceVersion
resourceVersion)
{
- this.versionSuffix = Args.notEmpty(versionSuffix,
"versionSuffix");
+ this(DEFAULT_VERSION_PREFIX, resourceVersion);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param versionPrefix
+ * string appended after the base filename before the
version string
+ * and followed by the extension
+ * @param resourceVersion
+ * resource version object
+ */
+ public FilenameWithVersionResourceCachingStrategy(String versionPrefix,
+ IResourceVersion
resourceVersion)
+ {
+ this.resourceVersion = Args.notNull(resourceVersion,
"resourceVersion");
+ this.versionPrefix = Args.notEmpty(versionPrefix,
"versionPrefix");
}
/**
* @return string appended to the filename before the version string
*/
- public final String getVersionSuffix()
+ public final String getVersionPrefix()
{
- return versionSuffix;
+ return versionPrefix;
}
public void decorateUrl(ResourceUrl url, ResourceReference reference)
{
// get version string for requested resource
- final String version = getVersionStringForResource(reference);
-
+ final String version =
this.resourceVersion.getVersion(reference);
+
// ignore resource if no version information is available
if (version == null)
{
@@ -84,7 +111,7 @@ public abstract class AbstractFilenameWi
// create filename with version:
//
// filename :=
- // [basename][version-suffix][version](.extension)
+ // [basename][version-prefix][version](.extension)
//
final StringBuilder versionedFilename = new StringBuilder();
@@ -98,7 +125,7 @@ public abstract class AbstractFilenameWi
versionedFilename.append(filename.substring(0,
extensionAt));
}
// add version suffix
- versionedFilename.append(versionSuffix);
+ versionedFilename.append(versionPrefix);
// add version
versionedFilename.append(version);
@@ -126,7 +153,7 @@ public abstract class AbstractFilenameWi
final String extension = pos == -1 ? null :
filename.substring(pos);
// get position of version string
- pos = fullname.lastIndexOf(versionSuffix);
+ pos = fullname.lastIndexOf(versionPrefix);
// remove version string if it exists
if (pos != -1)
@@ -141,15 +168,6 @@ public abstract class AbstractFilenameWi
}
/**
- * get string that uniquely identifies the current version of the
resource
- *
- * @param reference
- * resource reference
- * @return string that uniquely identifies the current version of the
resource
- */
- protected abstract String getVersionStringForResource(ResourceReference
reference);
-
- /**
* set resource caching to maximum and set cache-visibility to 'public'
*
* @param response
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/IResourceCachingStrategy.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/IResourceCachingStrategy.java?rev=1141298&r1=1141297&r2=1141298&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/IResourceCachingStrategy.java
(original)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/IResourceCachingStrategy.java
Wed Jun 29 22:32:59 2011
@@ -22,10 +22,13 @@ import org.apache.wicket.request.resourc
/**
* caching strategy for resources
* <p/>
- * it can add and remove caching information to the filename and query string
parameters of the
- * requested resource
+ * it can add and remove caching information to the filename and query
+ * string parameters of the requested resource to control caches in the
+ * browser and on the internet. It also can set http response caching headers.
*
* @author Peter Ertl
+ *
+ * @since 1.5
*/
public interface IResourceCachingStrategy
{
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/NoOpResourceCachingStrategy.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/NoOpResourceCachingStrategy.java?rev=1141298&r1=1141297&r2=1141298&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/NoOpResourceCachingStrategy.java
(original)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/NoOpResourceCachingStrategy.java
Wed Jun 29 22:32:59 2011
@@ -21,13 +21,17 @@ import org.apache.wicket.request.resourc
/**
* resource caching strategy that does nothing
+ * <p/>
+ * caching will resources will effectively be disabled
*
* @author Peter Ertl
+ *
+ * @since 1.5
*/
public class NoOpResourceCachingStrategy implements IResourceCachingStrategy
{
/**
- * Global instance of noop strategy
+ * Global instance of {@link NoOpResourceCachingStrategy} strategy
*/
public static final IResourceCachingStrategy INSTANCE = new
NoOpResourceCachingStrategy();
Copied:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/QueryStringWithVersionResourceCachingStrategy.java
(from r1141191,
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/QueryStringWithTimestampResourceCachingStrategy.java)
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/QueryStringWithVersionResourceCachingStrategy.java?p2=wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/QueryStringWithVersionResourceCachingStrategy.java&p1=wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/QueryStringWithTimestampResourceCachingStrategy.java&r1=1141191&r2=1141298&rev=1141298&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/QueryStringWithTimestampResourceCachingStrategy.java
(original)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/QueryStringWithVersionResourceCachingStrategy.java
Wed Jun 29 22:32:59 2011
@@ -20,57 +20,73 @@ import org.apache.wicket.request.http.We
import org.apache.wicket.request.mapper.parameter.INamedParameters;
import org.apache.wicket.request.resource.AbstractResource;
import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.request.resource.caching.version.IResourceVersion;
import org.apache.wicket.util.lang.Args;
-import org.apache.wicket.util.time.Time;
/**
* resource caching strategy that adds a last-modified timestamp to the query
string of the resource
* (this is similar to how wicket 1.4 does it when enabling timestamps on
resources).
*
* @author Peter Ertl
+ *
+ * @since 1.5
*/
-public class QueryStringWithTimestampResourceCachingStrategy extends
- AbstractResourceCachingStrategy
+public class QueryStringWithVersionResourceCachingStrategy implements
IResourceCachingStrategy
{
- private static final String DEFAULT_TIMESTAMP_PARAMETER = "ts";
+ private static final String DEFAULT_VERSION_PARAMETER = "ver";
+
+ /**
+ * query string parameter name that contains the version string for the
resource
+ */
+ private final String versionParameter;
- private final String timestampParameter;
+ /**
+ * resource version provider
+ */
+ private final IResourceVersion resourceVersion;
/**
* Constructor
+ *
+ * @param resourceVersion
+ * resource version provider
*/
- public QueryStringWithTimestampResourceCachingStrategy()
+ public QueryStringWithVersionResourceCachingStrategy(IResourceVersion
resourceVersion)
{
- this(DEFAULT_TIMESTAMP_PARAMETER);
+ this(DEFAULT_VERSION_PARAMETER, resourceVersion);
}
/**
* Constructor
- *
- * @param timestampParameter
+ *
+ * @param versionParameter
* name of timestamp parameter which will be added to query
string
+ * and contain the resource version string
+ * @param resourceVersion
+ * resource version provider
*/
- public QueryStringWithTimestampResourceCachingStrategy(String
timestampParameter)
+ public QueryStringWithVersionResourceCachingStrategy(String
versionParameter,
+ IResourceVersion
resourceVersion)
{
- Args.notEmpty(timestampParameter, "timestampParameter");
- this.timestampParameter = timestampParameter;
+ this.versionParameter = Args.notEmpty(versionParameter,
"timestampParameter");
+ this.resourceVersion = Args.notNull(resourceVersion,
"resourceVersion");
}
/**
* @return name of timestamp parameter which will be added to query
string
*/
- public final String getTimestampParameter()
+ public final String getVersionParameter()
{
- return timestampParameter;
+ return versionParameter;
}
public void decorateUrl(ResourceUrl url, final ResourceReference
reference)
{
- Time lastModified = getLastModified(reference);
+ String version = resourceVersion.getVersion(reference);
- if (lastModified != null)
+ if (version != null)
{
- url.getParameters().set(timestampParameter,
lastModified.getMilliseconds());
+ url.getParameters().set(versionParameter, version);
}
}
@@ -80,7 +96,7 @@ public class QueryStringWithTimestampRes
if (parameters != null)
{
- parameters.remove(timestampParameter);
+ parameters.remove(versionParameter);
}
}
Added:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/CachingResourceVersion.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/CachingResourceVersion.java?rev=1141298&view=auto
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/CachingResourceVersion.java
(added)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/CachingResourceVersion.java
Wed Jun 29 22:32:59 2011
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.wicket.request.resource.caching.version;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * Caches the results of a delegating {@link IResourceVersion} instance
+ *
+ * @autor Peter Ertl
+ *
+ * @since 1.5
+ */
+public class CachingResourceVersion implements IResourceVersion
+{
+ private static final String NULL_VALUE = "null";
+
+ private final IResourceVersion delegate;
+ private final ConcurrentMap<ResourceReference, String> cache;
+
+ public CachingResourceVersion(IResourceVersion delegate)
+ {
+ this.delegate = Args.notNull(delegate, "delegate");
+ this.cache = new ConcurrentHashMap<ResourceReference, String>();
+ }
+
+ public String getVersion(ResourceReference resourceReference)
+ {
+ String version = cache.get(resourceReference);
+
+ if (version == null)
+ {
+ version = delegate.getVersion(resourceReference);
+
+ if (version == null)
+ {
+ version = NULL_VALUE;
+ }
+ cache.put(resourceReference, version);
+ }
+
+ //noinspection StringEquality
+ if (version == NULL_VALUE)
+ {
+ return null;
+ }
+ return version;
+ }
+}
Added:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/IResourceVersion.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/IResourceVersion.java?rev=1141298&view=auto
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/IResourceVersion.java
(added)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/IResourceVersion.java
Wed Jun 29 22:32:59 2011
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.wicket.request.resource.caching.version;
+
+import org.apache.wicket.request.resource.ResourceReference;
+
+/**
+ * Provides a version string for a resource specified by {@link
ResourceReference}
+ * <p/>
+ * the version string will be used as a caching key for resources
+ *
+ * @see
org.apache.wicket.request.resource.caching.QueryStringWithVersionResourceCachingStrategy
+ * @see
org.apache.wicket.request.resource.caching.FilenameWithVersionResourceCachingStrategy
+ *
+ * @author Peter Ertl
+ *
+ * @since 1.5
+ */
+public interface IResourceVersion
+{
+ /**
+ * get unique string identifying the version of the resource
+ *
+ * @param resourceReference
+ * reference to resource
+ * @return unique version string
+ */
+ String getVersion(ResourceReference resourceReference);
+}
Added:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/LastModifiedResourceVersion.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/LastModifiedResourceVersion.java?rev=1141298&view=auto
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/LastModifiedResourceVersion.java
(added)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/LastModifiedResourceVersion.java
Wed Jun 29 22:32:59 2011
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.wicket.request.resource.caching.version;
+
+import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.time.Time;
+
+/**
+ * Uses the last modified timestamp of a {@link ResourceReference}
+ * in milliseconds as a version string.
+ *
+ * @author Peter Ertl
+ *
+ * @since 1.5
+ */
+public class LastModifiedResourceVersion implements IResourceVersion
+{
+ public String getVersion(ResourceReference resourceReference)
+ {
+ final Time lastModified = resourceReference.getLastModified();
+
+ if (lastModified == null)
+ {
+ return null;
+ }
+ return String.valueOf(lastModified.getMilliseconds());
+ }
+}
Added:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/MessageDigestResourceVersion.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/MessageDigestResourceVersion.java?rev=1141298&view=auto
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/MessageDigestResourceVersion.java
(added)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/MessageDigestResourceVersion.java
Wed Jun 29 22:32:59 2011
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.wicket.request.resource.caching.version;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.request.resource.IResource;
+import org.apache.wicket.request.resource.PackageResource;
+import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.io.IOUtils;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.resource.IResourceStream;
+import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * uses the message digest of a {@link PackageResource} as a version string
+ *
+ * @author Peter Ertl
+ *
+ * @since 1.5
+ */
+public class MessageDigestResourceVersion implements IResourceVersion
+{
+ private static final Logger log =
LoggerFactory.getLogger(MessageDigestResourceVersion.class);
+
+ private static final String DEFAULT_ALGORITHM = "MD5";
+ private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+ /** message digest algorithm for computing hashes */
+ private final String algorithm;
+
+ /** buffer size for computing the digest */
+ private final int bufferSize;
+
+ /**
+ * create an instance using {@value #DEFAULT_ALGORITHM}
+ */
+ public MessageDigestResourceVersion()
+ {
+ this(DEFAULT_ALGORITHM, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * create an instance using an algorihm that can be
+ * retrieved by Java Cryptography Architecture (JCA)
+ * using {@link MessageDigest#getInstance(String)} and
+ * using an fixed-size internal buffer for digest computation of
+ * {@value #DEFAULT_BUFFER_SIZE} bytes.
+ *
+ * @param algorithm
+ * digest algorithm
+ */
+ public MessageDigestResourceVersion(String algorithm)
+ {
+ this(algorithm, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * create an instance using an algorihm that can be
+ * retrieved by Java Cryptography Architecture (JCA)
+ * using {@link MessageDigest#getInstance(String)} and
+ * using an specified internal buffer for digest computation.
+ *
+ * @param algorithm
+ * digest algorithm
+ * @param bufferSize
+ * internal buffer size for digest computation
+ */
+ public MessageDigestResourceVersion(String algorithm, int bufferSize)
+ {
+ this.algorithm = Args.notEmpty(algorithm, "algorithm");
+ this.bufferSize = bufferSize;
+ }
+
+ public String getVersion(ResourceReference resourceReference)
+ {
+ final IResource resource = resourceReference.getResource();
+
+ if (PackageResource.class.isInstance(resource) == false)
+ {
+ log.warn("message digests are only available with
package " +
+ "resource, not with " + resourceReference);
+
+ return null;
+ }
+
+ // get resource data
+ final PackageResource packageResource =
(PackageResource)resource;
+ final IResourceStream resourceStream =
packageResource.getResourceStream();
+
+ if (resourceStream == null)
+ {
+ log.debug("could not get resource stream for " +
resource);
+ return null;
+ }
+
+ try
+ {
+ // get binary hash
+ final byte[] hash = computeDigest(resourceStream);
+
+ // convert to hexadecimal
+ return new BigInteger(hash).toString(16);
+ }
+ catch (ResourceStreamNotFoundException e)
+ {
+ log.warn("resource stream not found for " + resource);
+ return null;
+ }
+ catch (IOException e)
+ {
+ log.warn("resource stream not be read for " + resource,
e);
+ return null;
+ }
+ }
+
+ /**
+ * get instance of message digest provider from JCA
+ *
+ * @return message digest provider
+ */
+ protected MessageDigest getMessageDigest()
+ {
+ try
+ {
+ return MessageDigest.getInstance(algorithm);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new WicketRuntimeException("message digest " +
algorithm + " not found", e);
+ }
+ }
+
+ /**
+ * compute digest for resource stream
+ *
+ * @param resourceStream
+ * resource stream to compute message digest for
+ *
+ * @return binary message digest
+ *
+ * @throws ResourceStreamNotFoundException
+ * @throws IOException
+ */
+ protected byte[] computeDigest(IResourceStream resourceStream)
+ throws ResourceStreamNotFoundException, IOException
+ {
+ final MessageDigest digest = getMessageDigest();
+ final InputStream inputStream = resourceStream.getInputStream();
+
+ try
+ {
+ final byte[] buf = new byte[bufferSize];
+ int len;
+
+ while ((len = inputStream.read(buf)) != -1)
+ {
+ digest.update(buf, 0, len);
+ }
+ return digest.digest();
+ }
+ finally
+ {
+ IOUtils.closeQuietly(inputStream);
+ }
+ }
+}
Added:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/RequestCycleCachedResourceVersion.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/RequestCycleCachedResourceVersion.java?rev=1141298&view=auto
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/RequestCycleCachedResourceVersion.java
(added)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/RequestCycleCachedResourceVersion.java
Wed Jun 29 22:32:59 2011
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.wicket.request.resource.caching.version;
+
+import java.util.Map;
+
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.ThreadContext;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.lang.Generics;
+
+/**
+ * Caches the results of a delegating {@link IResourceVersion} instance
+ * in the current request meta data. It will be cached for the lifetime
+ * of the current http request.
+ *
+ * @author Peter Ertl
+ *
+ * @since 1.5
+ */
+public class RequestCycleCachedResourceVersion implements IResourceVersion
+{
+ private static final MetaDataKey<Map<ResourceReference, String>>
CACHE_KEY =
+ new MetaDataKey<Map<ResourceReference, String>>()
+ {
+ private static final long serialVersionUID = 1L;
+ };
+
+ /**
+ * resource version provider which will actually do
+ * the work and retrieve the version
+ */
+ private final IResourceVersion delegate;
+
+ /**
+ * Constructor
+ *
+ * @param delegate
+ * resource version provider to cache
+ */
+ public RequestCycleCachedResourceVersion(IResourceVersion delegate)
+ {
+ this.delegate = Args.notNull(delegate, "delegate");
+ }
+
+ public String getVersion(ResourceReference resourceReference)
+ {
+ // get current request cycle
+ final RequestCycle requestCycle =
ThreadContext.getRequestCycle();
+
+ Map<ResourceReference, String> cache = null;
+
+ // is request cycle available?
+ if (requestCycle != null)
+ {
+ // retrieve cache from current request cycle
+ cache = requestCycle.getMetaData(CACHE_KEY);
+
+ // create it on first call
+ if (cache == null)
+ {
+ requestCycle.setMetaData(CACHE_KEY, cache =
Generics.newHashMap());
+ }
+
+ // lookup timestamp from cache (may contain NULL values
which are valid)
+ if (cache.containsKey(resourceReference))
+ {
+ return cache.get(resourceReference);
+ }
+ }
+
+ // no cache entry found, query version from delegate
+ final String version = delegate.getVersion(resourceReference);
+
+ // store value in cache (if it is available)
+ if (cache != null)
+ {
+ cache.put(resourceReference, version);
+ }
+
+ return version;
+ }
+}
Added:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/StaticResourceVersion.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/StaticResourceVersion.java?rev=1141298&view=auto
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/StaticResourceVersion.java
(added)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/request/resource/caching/version/StaticResourceVersion.java
Wed Jun 29 22:32:59 2011
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.wicket.request.resource.caching.version;
+
+import org.apache.wicket.request.resource.ResourceReference;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * provides a static version string for all queries resources
+ *
+ * @author Peter Ertl
+ *
+ * @since 1.5
+ */
+public class StaticResourceVersion implements IResourceVersion
+{
+ private final String version;
+
+ /**
+ * Constructor
+ *
+ * @param version
+ * static version string to deliver for all queries
resources
+ */
+ public StaticResourceVersion(String version)
+ {
+ this.version = Args.notNull(version, "version");
+ }
+
+ public String getVersion(ResourceReference resourceReference)
+ {
+ return version;
+ }
+}
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/ResourceSettings.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/ResourceSettings.java?rev=1141298&r1=1141297&r2=1141298&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/ResourceSettings.java
(original)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/ResourceSettings.java
Wed Jun 29 22:32:59 2011
@@ -27,9 +27,14 @@ import org.apache.wicket.javascript.IJav
import org.apache.wicket.markup.html.IPackageResourceGuard;
import org.apache.wicket.markup.html.PackageResourceGuard;
import org.apache.wicket.request.http.WebResponse;
-import
org.apache.wicket.request.resource.caching.FilenameWithTimestampResourceCachingStrategy;
+import
org.apache.wicket.request.resource.caching.FilenameWithVersionResourceCachingStrategy;
import org.apache.wicket.request.resource.caching.IResourceCachingStrategy;
import org.apache.wicket.request.resource.caching.NoOpResourceCachingStrategy;
+import
org.apache.wicket.request.resource.caching.version.CachingResourceVersion;
+import org.apache.wicket.request.resource.caching.version.IResourceVersion;
+import
org.apache.wicket.request.resource.caching.version.LastModifiedResourceVersion;
+import
org.apache.wicket.request.resource.caching.version.MessageDigestResourceVersion;
+import
org.apache.wicket.request.resource.caching.version.RequestCycleCachedResourceVersion;
import org.apache.wicket.resource.PropertiesFactory;
import org.apache.wicket.resource.loader.ClassStringResourceLoader;
import org.apache.wicket.resource.loader.ComponentStringResourceLoader;
@@ -112,8 +117,10 @@ public class ResourceSettings implements
private String parentFolderPlaceholder = null;
// resource caching strategy
- private IResourceCachingStrategy resourceCachingStrategy = new
FilenameWithTimestampResourceCachingStrategy();
-
+ private IResourceCachingStrategy resourceCachingStrategy;
+
+ // application these settings are bound to
+ private final Application application;
/**
* Construct
@@ -122,6 +129,7 @@ public class ResourceSettings implements
*/
public ResourceSettings(final Application application)
{
+ this.application = application;
stringResourceLoaders.add(new ComponentStringResourceLoader());
stringResourceLoaders.add(new PackageStringResourceLoader());
stringResourceLoaders.add(new
ClassStringResourceLoader(application.getClass()));
@@ -426,6 +434,23 @@ public class ResourceSettings implements
*/
public IResourceCachingStrategy getCachingStrategy()
{
+ if (resourceCachingStrategy == null)
+ {
+ final IResourceVersion resourceVersion;
+
+ if (application.usesDevelopmentConfig())
+ {
+ // use file last modified for resource cache
keys
+ resourceVersion = new
RequestCycleCachedResourceVersion(new LastModifiedResourceVersion());
+ }
+ else
+ {
+ // use md5 message digest for resource cache
keys
+ resourceVersion = new
CachingResourceVersion(new MessageDigestResourceVersion());
+ }
+ resourceCachingStrategy =
+ new
FilenameWithVersionResourceCachingStrategy(resourceVersion);
+ }
return resourceCachingStrategy;
}
Modified:
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/mapper/BasicResourceReferenceMapperTest.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/mapper/BasicResourceReferenceMapperTest.java?rev=1141298&r1=1141297&r2=1141298&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/mapper/BasicResourceReferenceMapperTest.java
(original)
+++
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/request/mapper/BasicResourceReferenceMapperTest.java
Wed Jun 29 22:32:59 2011
@@ -18,26 +18,23 @@ package org.apache.wicket.request.mapper
import java.util.Locale;
-import org.apache.wicket.ThreadContext;
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.Url;
-import org.apache.wicket.request.cycle.RequestCycle;
import
org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler;
import org.apache.wicket.request.mapper.parameter.INamedParameters;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.request.mapper.parameter.PageParametersEncoder;
import org.apache.wicket.request.resource.IResource;
import org.apache.wicket.request.resource.ResourceReference;
-import
org.apache.wicket.request.resource.caching.FilenameWithStaticVersionResourceCachingStrategy;
-import
org.apache.wicket.request.resource.caching.FilenameWithTimestampResourceCachingStrategy;
+import
org.apache.wicket.request.resource.caching.FilenameWithVersionResourceCachingStrategy;
import org.apache.wicket.request.resource.caching.IResourceCachingStrategy;
import org.apache.wicket.request.resource.caching.NoOpResourceCachingStrategy;
import org.apache.wicket.request.resource.caching.ResourceUrl;
+import
org.apache.wicket.request.resource.caching.version.LastModifiedResourceVersion;
+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.tester.WicketTester;
import org.apache.wicket.util.time.Time;
-import org.mockito.Mockito;
/**
* @author Matej Knopp
@@ -47,8 +44,9 @@ public class BasicResourceReferenceMappe
private static final IProvider<IResourceCachingStrategy> NO_CACHING =
new ValueProvider<IResourceCachingStrategy>(
NoOpResourceCachingStrategy.INSTANCE);
- private static final
IProvider<FilenameWithTimestampResourceCachingStrategy>
CACHE_FILENAME_WITH_TIMESTAMP = new
ValueProvider<FilenameWithTimestampResourceCachingStrategy>(
- new FilenameWithTimestampResourceCachingStrategy());
+ private static final
IProvider<FilenameWithVersionResourceCachingStrategy>
CACHE_FILENAME_WITH_TIMESTAMP =
+ new ValueProvider<FilenameWithVersionResourceCachingStrategy>(
+ new FilenameWithVersionResourceCachingStrategy(new
LastModifiedResourceVersion()));
/**
* Construct.
@@ -461,47 +459,11 @@ public class BasicResourceReferenceMappe
Url url = encoderWithTimestamps.mapHandler(handler);
// check that url contains timestamp
- String timestampPart =
CACHE_FILENAME_WITH_TIMESTAMP.get().getVersionSuffix() +
+ String timestampPart =
CACHE_FILENAME_WITH_TIMESTAMP.get().getVersionPrefix() +
Long.toString(millis) + "?";
assertTrue(url.toString().contains(timestampPart));
}
- /**
- *
- */
- public void testLastModifiedTimestampCache()
- {
- long millis = 87654321L;
- final ResourceReferenceWithTimestamp reference = new
ResourceReferenceWithTimestamp(
- Time.millis(millis));
- final IRequestHandler handler = new
ResourceReferenceRequestHandler(reference, null);
-
- WicketTester tester = new WicketTester();
-
- // setup mock request cycle
- RequestCycle cycle = Mockito.mock(RequestCycle.class);
- ThreadContext.setRequestCycle(cycle);
-
- // request url with timestamp
- Url url1 = encoderWithTimestamps.mapHandler(handler);
- assertNotNull(url1);
- assertEquals(1, reference.lastModifiedInvocationCount);
-
- // subsequent request should take timestamp from request cycle
scoped cache
- Url url2 = encoderWithTimestamps.mapHandler(handler);
- assertNotNull(url2);
-
- Url url3 = encoderWithTimestamps.mapHandler(handler);
- assertNotNull(url3);
-
- assertEquals(1, reference.lastModifiedInvocationCount);
-
- // urls should be equal
- assertEquals(url1, url2);
- assertEquals(url1, url3);
- tester.destroy();
- }
-
public void testVersionStringInResourceFilename()
{
final IResource resource = new IResource()
@@ -521,8 +483,8 @@ public class BasicResourceReferenceMappe
}
};
- FilenameWithStaticVersionResourceCachingStrategy strategy =
- new
FilenameWithStaticVersionResourceCachingStrategy("-version-", "foobar");
+ IResourceCachingStrategy strategy =
+ new
FilenameWithVersionResourceCachingStrategy("-version-", new
StaticResourceVersion("foobar"));
INamedParameters params = new PageParameters();
ResourceUrl url = new ResourceUrl("test.js", params);
@@ -562,7 +524,7 @@ public class BasicResourceReferenceMappe
assertEquals("test.txt", url.getFileName());
// check a version that contains a dot which also marks the
filename extension
- strategy = new
FilenameWithStaticVersionResourceCachingStrategy("-version-", "1.0.4-beta");
+ strategy = new
FilenameWithVersionResourceCachingStrategy("-version-", new
StaticResourceVersion("1.0.4-beta"));
url = new ResourceUrl("test.txt", params);
strategy.decorateUrl(url, reference);
assertEquals("test-version-1.0.4-beta.txt", url.getFileName());