You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2007/11/19 02:27:35 UTC

svn commit: r596175 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry/internal/events/ main/java/org/apache/tapestry/internal/services/ main/java/org/apache/tapestry/internal/util/ test/java/org/apache/tapestry/internal/util/

Author: hlship
Date: Sun Nov 18 17:27:34 2007
New Revision: 596175

URL: http://svn.apache.org/viewvc?rev=596175&view=rev
Log:
TAPESTRY-1918: Tapestry's reload logic should be able to see additions, not just deletions and changes

Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/events/InvalidationListener.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.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/util/URLChangeTrackerTest.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/events/InvalidationListener.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/events/InvalidationListener.java?rev=596175&r1=596174&r2=596175&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/events/InvalidationListener.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/events/InvalidationListener.java Sun Nov 18 17:27:34 2007
@@ -1,23 +1,22 @@
-// Copyright 2006, 2007 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.
-
+// Copyright 2006, 2007 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.tapestry.internal.events;
 
 /**
- * Interface for objects that may cache information that can be invalidated.
- *
- * @see org.apache.tapestry.internal.events.InvalidationEvent
+ * Interface for objects that may cache information that can be invalidated. Invalidation occurs
+ * when external files, from which in-memory data is cached, is determined to have changed.
  */
 public interface InvalidationListener
 {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java?rev=596175&r1=596174&r2=596175&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java Sun Nov 18 17:27:34 2007
@@ -34,8 +34,7 @@
  * A wrapper around a Javassist class loader that allows certain classes to be modified as they are
  * loaded.
  */
-public final class ComponentInstantiatorSourceImpl extends InvalidationEventHubImpl implements
-                                                                                    Translator, ComponentInstantiatorSource, UpdateListener
+public final class ComponentInstantiatorSourceImpl extends InvalidationEventHubImpl implements Translator, ComponentInstantiatorSource, UpdateListener
 {
     /**
      * Add -Djavassist-write-dir=target/transformed-classes to the command line to force output of
@@ -49,8 +48,6 @@
 
     private final ClassLoader _parent;
 
-    private ClassFactoryClassPool _classPool;
-
     private Loader _loader;
 
     private final ComponentClassTransformer _transformer;
@@ -74,8 +71,7 @@
         @Override
         protected Class findClass(String className) throws ClassNotFoundException
         {
-            if (inControlledPackage(className))
-                return super.findClass(className);
+            if (inControlledPackage(className)) return super.findClass(className);
 
             // Returning null forces delegation to the parent class loader.
 
@@ -84,8 +80,7 @@
 
     }
 
-    public ComponentInstantiatorSourceImpl(ClassLoader parent,
-                                           ComponentClassTransformer transformer, Logger logger)
+    public ComponentInstantiatorSourceImpl(ClassLoader parent, ComponentClassTransformer transformer, Logger logger)
     {
         _parent = parent;
         _transformer = transformer;
@@ -96,8 +91,7 @@
 
     public synchronized void checkForUpdates()
     {
-        if (!_changeTracker.containsChanges())
-            return;
+        if (!_changeTracker.containsChanges()) return;
 
         _changeTracker.clear();
         _instantiatorMap.clear();
@@ -119,29 +113,28 @@
      */
     private void initializeService()
     {
-        _classPool = new ClassFactoryClassPool(_parent);
+        ClassFactoryClassPool classPool = new ClassFactoryClassPool(_parent);
 
-        _loader = new PackageAwareLoader(_parent, _classPool);
+        _loader = new PackageAwareLoader(_parent, classPool);
 
         ClassPath path = new LoaderClassPath(_loader);
 
-        _classPool.appendClassPath(path);
+        classPool.appendClassPath(path);
 
         try
         {
-            _loader.addTranslator(_classPool, this);
+            _loader.addTranslator(classPool, this);
         }
         catch (Exception ex)
         {
             throw new RuntimeException(ex);
         }
 
-        _classFactory = new ClassFactoryImpl(_loader, _classPool, _logger);
+        _classFactory = new ClassFactoryImpl(_loader, classPool, _logger);
     }
 
     // This is called from well within a synchronized block.
-    public void onLoad(ClassPool pool, String classname) throws NotFoundException,
-                                                                CannotCompileException
+    public void onLoad(ClassPool pool, String classname) throws NotFoundException, CannotCompileException
     {
         _logger.debug("BEGIN onLoad " + classname);
 
@@ -185,8 +178,7 @@
 
     private void writeClassToFileSystemForHardCoreDebuggingPurposesOnly(CtClass ctClass)
     {
-        if (JAVASSIST_WRITE_DIR == null)
-            return;
+        if (JAVASSIST_WRITE_DIR == null) return;
 
         try
         {
@@ -211,8 +203,7 @@
         _changeTracker.add(url);
     }
 
-    private void forceSuperclassTransform(CtClass ctClass) throws NotFoundException,
-                                                                  ClassNotFoundException
+    private void forceSuperclassTransform(CtClass ctClass) throws NotFoundException, ClassNotFoundException
     {
         CtClass superClass = ctClass.getSuperclass();
 
@@ -265,8 +256,7 @@
 
         while (packageName != null)
         {
-            if (_controlledPackageNames.contains(packageName))
-                return true;
+            if (_controlledPackageNames.contains(packageName)) return true;
 
             packageName = stripTail(packageName);
         }
@@ -278,8 +268,7 @@
     {
         int lastdot = input.lastIndexOf('.');
 
-        if (lastdot < 0)
-            return null;
+        if (lastdot < 0) return null;
 
         return input.substring(0, lastdot);
     }

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?rev=596175&r1=596174&r2=596175&view=diff
==============================================================================
--- 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 Sun Nov 18 17:27:34 2007
@@ -72,13 +72,24 @@
             URI resourceURI = url.toURI();
             File resourceFile = new File(resourceURI);
 
-            if (_fileToTimestamp.containsKey(resourceFile))
-                return _fileToTimestamp.get(resourceFile);
+            if (_fileToTimestamp.containsKey(resourceFile)) return _fileToTimestamp.get(resourceFile);
 
             long timestamp = readTimestamp(resourceFile);
 
+            // A quick and imperfect fix for TAPESTRY-1918.  When a file
+            // is added, add the directory containing the file as well.
+
             _fileToTimestamp.put(resourceFile, timestamp);
 
+            File dir = resourceFile.getParentFile();
+
+            if (!_fileToTimestamp.containsKey(dir))
+            {
+                long dirTimestamp = readTimestamp(dir);
+                _fileToTimestamp.put(dir, dirTimestamp);
+            }
+
+
             return timestamp;
         }
         catch (URISyntaxException ex)
@@ -130,7 +141,14 @@
         if (!file.exists()) return FILE_DOES_NOT_EXIST_TIMESTAMP;
 
         long timestamp = file.lastModified();
+
+        // For coarse granularity (accurate only to the last second), remove the milliseconds since
+        // the last full second. This is for compatibility with client HTTP requests, which
+        // are only accurate to one second. The extra level of detail creates false positives
+        // for changes, and undermines HTTP response caching in the client.
+
         if (_granularitySeconds) timestamp -= timestamp % 1000;
+
         return timestamp;
     }
 

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?rev=596175&r1=596174&r2=596175&view=diff
==============================================================================
--- 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 Sun Nov 18 17:27:34 2007
@@ -40,7 +40,9 @@
 
         t.add(url);
 
-        assertEquals(t.trackedFileCount(), 1);
+        // The file, and the directory containing the file.
+
+        assertEquals(t.trackedFileCount(), 2);
 
         assertFalse(t.containsChanges());
 
@@ -67,6 +69,40 @@
     }
 
     @Test
+    public void creating_a_new_file_is_a_change() throws Exception
+    {
+        URLChangeTracker t = new URLChangeTracker();
+
+        File f = File.createTempFile("changetracker0", ".tmp");
+        URL url = f.toURL();
+
+        t.add(url);
+
+        assertFalse(t.containsChanges());
+
+        File dir = f.getParentFile();
+
+        // Create another file in the temporary directory.
+
+        long timestamp = dir.lastModified();
+
+        while (true)
+        {
+            File.createTempFile("changetracker1", ".tmp");
+
+            if (dir.lastModified() != timestamp) break;
+
+            // Sometime Java need a moment to catch up in terms of
+            // file system changes. Sleep for a few milliseconds
+            // and wait for it to catch up.
+
+            Thread.sleep(100);
+        }
+
+        assertTrue(t.containsChanges());
+    }
+
+    @Test
     public void non_file_URLs_are_ignored() throws Exception
     {
         URLChangeTracker t = new URLChangeTracker();
@@ -115,7 +151,8 @@
 
         assertTrue(timeModified > 0);
 
-        assertEquals(t.trackedFileCount(), 1);
+        // File + Directory
+        assertEquals(t.trackedFileCount(), 2);
 
         assertFalse(t.containsChanges());