org.apache.wicket.request.resource.caching.FilenameWithTimestampResourceCachingStrategy Maven / Gradle / Ivy
Go to download
A module that creates a .jar from the classes in wicket, wicket-util and wicket-request modules in order
to create a valid OSGi bundle of the wicket framework.
The newest version!
/*
* 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;
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.util.lang.Args;
import org.apache.wicket.util.time.Time;
/**
* resource caching strategy that adds a last-modified timestamp to the filename
*
* timestamped_filename := [basename][timestamp-prefix][last-modified-milliseconds](.extension)
*
* Normally the resource names won't change when the resource ifself changes, for example when you
* add a new style to your CSS sheet. This can be very annoying as browsers (and proxies) usally
* cache resources in their cache based on the filename and therefore won't update. Unless you
* change the file name of the resource, force a reload or clear the browser's cache the page will
* still render with your old CSS.
*
* Depending on HTTP response headers like 'Last-Modified' and 'Cache' automatic cache invalidation
* can take very, very long or neven happen at all.
*
* Enabling timestamps on resources with this strategy will inject the last modification time of the
* resource into the filename (the name will look something like 'style-ts1282915831000.css' where
* the large number is the last modified date in milliseconds and '-ts' is a prefix to avoid
* conflicts with filenames that already contain a number before their extension. *
*
* Since browsers and proxies use the filename of the resource as a cache key the changed filename
* will not hit the cache and the page gets rendered with the changed file.
*
*
* @author Peter Ertl
*/
public class FilenameWithTimestampResourceCachingStrategy extends AbstractResourceCachingStrategy
{
protected static final String DEFAULT_TIMESTAMP_SUFFIX = "-ts";
private final String timestampPrefix;
/**
* Constructor
*/
public FilenameWithTimestampResourceCachingStrategy()
{
this(DEFAULT_TIMESTAMP_SUFFIX);
}
/**
* Constructor
*
* @param timestampSuffix
* string appended to the filename before the timestamp
*/
public FilenameWithTimestampResourceCachingStrategy(String timestampSuffix)
{
Args.notEmpty(timestampSuffix, "timestampPrefix");
timestampPrefix = timestampSuffix;
}
/**
* @return string appended to the filename before the timestamp
*/
public final String getTimestampPrefix()
{
return timestampPrefix;
}
public void decorateUrl(ResourceUrl url, ResourceReference reference)
{
Time lastModified = getLastModified(reference);
final String filename = url.getFileName();
if (lastModified == null)
return;
// check if resource name has extension
int extensionAt = filename.lastIndexOf('.');
// create timestamped version of filename:
//
// filename :=
// [basename][timestamp-prefix][last-modified-milliseconds](.extension)
//
StringBuilder timestampedFilename = new StringBuilder();
timestampedFilename.append(extensionAt == -1 ? filename
: filename.substring(0, extensionAt));
timestampedFilename.append(timestampPrefix);
timestampedFilename.append(lastModified.getMilliseconds());
if (extensionAt != -1)
timestampedFilename.append(filename.substring(extensionAt));
url.setFileName(timestampedFilename.toString());
}
public void undecorateUrl(ResourceUrl url)
{
final String filename = url.getFileName();
int pos = filename.lastIndexOf('.');
final String fullname = pos == -1 ? filename : filename.substring(0, pos);
final String extension = pos == -1 ? null : filename.substring(pos);
pos = fullname.lastIndexOf(timestampPrefix);
if (pos != -1)
{
final String timestamp = fullname.substring(pos + timestampPrefix.length());
final String basename = fullname.substring(0, pos);
try
{
Long.parseLong(timestamp); // just check the timestamp is numeric
// create filename without timestamp for resource lookup
url.setFileName(extension == null ? basename : basename + extension);
return;
}
catch (NumberFormatException e)
{
// some strange case of coincidence where the filename contains the timestamp prefix
// but the timestamp itself is non-numeric - we interpret this situation as
// "file has no timestamp"
}
}
}
/**
* set resource caching to maximum and set cache-visibility to 'public'
*
* @param response
*/
public void decorateResponse(AbstractResource.ResourceResponse response)
{
response.setCacheDurationToMaximum();
response.setCacheScope(WebResponse.CacheScope.PUBLIC);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy