Author: gredler
Date: Sat Jun 16 13:11:56 2007
New Revision: 547974
URL: http://svn.apache.org/viewvc?view=rev&rev=547974
Log:
TAPESTRY-1447: URLChangeTracker should track changes in seconds (rather than
milliseconds) when dealing with resources in order to match granularity of HTTP
headers (Last-Modified, If-Modified-Since, Expires, etc).
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetDispatcher.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResourceCacheImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/util/URLChangeTracker.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ResourceCacheImplTest.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/util/URLChangeTrackerTest.java
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetDispatcher.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetDispatcher.java?view=diff&rev=547974&r1=547973&r2=547974
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetDispatcher.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetDispatcher.java
Sat Jun 16 13:11:56 2007
@@ -82,10 +82,14 @@
}
long ifModifiedSince = request.getDateHeader(IF_MODIFIED_SINCE_HEADER);
- if (ifModifiedSince > 0 && ifModifiedSince >=
_resourceCache.getTimeModified(resource))
+ if (ifModifiedSince > 0)
{
- response.sendError(HttpServletResponse.SC_NOT_MODIFIED, "");
- return true;
+ long modified = _resourceCache.getTimeModified(resource);
+ if (ifModifiedSince >= modified)
+ {
+ response.sendError(HttpServletResponse.SC_NOT_MODIFIED, "");
+ return true;
+ }
}
_streamer.streamResource(resource);
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResourceCacheImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResourceCacheImpl.java?view=diff&rev=547974&r1=547973&r2=547974
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResourceCacheImpl.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ResourceCacheImpl.java
Sat Jun 16 13:11:56 2007
@@ -65,13 +65,8 @@
public ResourceCacheImpl(final ResourceDigestGenerator digestGenerator)
{
- this(digestGenerator, new URLChangeTracker());
- }
-
- ResourceCacheImpl(final ResourceDigestGenerator digestGenerator,
URLChangeTracker tracker)
- {
_digestGenerator = digestGenerator;
- _tracker = tracker;
+ _tracker = new URLChangeTracker(true);
}
public void checkForUpdates()
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/util/URLChangeTracker.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/util/URLChangeTracker.java?view=diff&rev=547974&r1=547973&r2=547974
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/util/URLChangeTracker.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/util/URLChangeTracker.java
Sat Jun 16 13:11:56 2007
@@ -24,7 +24,10 @@
/**
* Given a (growing) set of URLs, can periodically check to see if any of the
underlying resources
- * has changed.
+ * has changed. This class is capable of using either millisecond-level
granularity or second-level
+ * granularity. Millisecond-level granularity is used by default. Second-level
granularity is
+ * provided for compatibility with browsers vis-a-vis resource caching --
that's how granular they
+ * get with their "If-Modified-Since", "Last-Modified" and "Expires" headers.
*/
public class URLChangeTracker
{
@@ -32,6 +35,28 @@
private final Map<File, Long> _fileToTimestamp = newConcurrentMap();
+ private boolean _granularitySeconds;
+
+ /**
+ * Creates a new URL change tracker with millisecond-level granularity.
+ */
+ public URLChangeTracker()
+ {
+ this(false);
+ }
+
+ /**
+ * Creates a new URL change tracker, using either millisecond-level
granularity or second-level
+ * granularity.
+ *
+ * @param granularitySeconds
+ * whether or not to use second-level granularity
+ */
+ public URLChangeTracker(boolean granularitySeconds)
+ {
+ _granularitySeconds = granularitySeconds;
+ }
+
/**
* Stores a new URL into the tracker, or returns the previous time stamp
for a previously added
* URL. Filters out all non-file URLs.
@@ -42,8 +67,7 @@
*/
public long add(URL url)
{
- if (!url.getProtocol().equals("file"))
- return 0;
+ if (!url.getProtocol().equals("file")) return 0;
try
{
@@ -90,8 +114,7 @@
long newTimestamp = readTimestamp(entry.getKey());
long current = entry.getValue();
- if (current == newTimestamp)
- continue;
+ if (current == newTimestamp) continue;
result = true;
entry.setValue(newTimestamp);
@@ -100,12 +123,17 @@
return result;
}
+ /**
+ * Returns the time that the specified file was last modified, possibly
rounded down to the
+ * nearest second.
+ */
private long readTimestamp(File file)
{
- if (!file.exists())
- return FILE_DOES_NOT_EXIST_TIMESTAMP;
+ if (!file.exists()) return FILE_DOES_NOT_EXIST_TIMESTAMP;
- return file.lastModified();
+ long timestamp = file.lastModified();
+ if (_granularitySeconds) timestamp -= timestamp % 1000;
+ return timestamp;
}
/**
@@ -125,4 +153,5 @@
{
return _fileToTimestamp.size();
}
+
}
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ResourceCacheImplTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ResourceCacheImplTest.java?view=diff&rev=547974&r1=547973&r2=547974
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ResourceCacheImplTest.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ResourceCacheImplTest.java
Sat Jun 16 13:11:56 2007
@@ -40,6 +40,7 @@
Resource r = mockResource();
long lastUpdated = f.lastModified();
+ lastUpdated -= lastUpdated % 1000;
train_getPath(r, PATH);
train_toURL(r, url);
@@ -90,6 +91,7 @@
Resource r = mockResource();
long lastUpdated = f.lastModified();
+ lastUpdated -= lastUpdated % 1000;
train_getPath(r, PATH);
train_toURL(r, url);
@@ -118,6 +120,7 @@
Resource r = mockResource();
long lastUpdated = f.lastModified();
+ lastUpdated -= lastUpdated % 1000;
train_getPath(r, PATH);
train_toURL(r, url);
@@ -140,9 +143,11 @@
verify();
+ Thread.sleep(1500);
touch(f);
lastUpdated = f.lastModified();
+ lastUpdated -= lastUpdated % 1000;
String expectedDigest = "FREDBARNEY";
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/util/URLChangeTrackerTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/util/URLChangeTrackerTest.java?view=diff&rev=547974&r1=547973&r2=547974
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/util/URLChangeTrackerTest.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/util/URLChangeTrackerTest.java
Sat Jun 16 13:11:56 2007
@@ -124,4 +124,30 @@
assertTrue(t.containsChanges());
}
+ @Test
+ public void second_level_granularity() throws Exception
+ {
+ URLChangeTracker t = new URLChangeTracker(true);
+
+ File f = File.createTempFile("changetracker0", ".tmp");
+ URL url = f.toURL();
+
+ touch(f);
+ long timestamp = t.add(url);
+ assertEquals(0, timestamp % 1000);
+ assertFalse(t.containsChanges());
+
+ touch(f);
+ timestamp = t.add(url);
+ assertEquals(0, timestamp % 1000);
+ assertFalse(t.containsChanges());
+
+ Thread.sleep(1500);
+
+ touch(f);
+ timestamp = t.add(url);
+ assertEquals(0, timestamp % 1000);
+ assertTrue(t.containsChanges());
+ }
+
}