In the ResourceManager class, 
  resource.process()
was always (twice) called before the function call
  resourceLoader.getLastModified( resource )
that gets the resource timestamp.


The problem is that if (with loads of bad luck) the 
resource is updated between these too calls, the old 
resource version data would be associated with the 
newer version timestamp.

The consequence is that the subsequent timestamp 
checks on the resource would give it has not changed.


These patch is not ideal but it is what is possible
with the current architecture (*). It simply consists 
in an order change - getting the timestamp before 
loading the resource.

Its worse case is that a new version of the resource,
changed (again) between the 2 calls will be loaded 
twice - because of the new version data being 
associated with the old timestamp. 

However, this just results in redundant work on the
very-bad-Murphy-at-work case instead of deficient
functionality (e.g.: an updated template not being 
reloaded).


As mentioned before, be aware that text newline 
sequences might be wrong for Linux (I'm not sure). 
And I am sure it will need some editing to work. 

Can some one fix it and apply it?


Thanks and have fun,
Paulo Gaspar

(*) - Anyway, I think it is impossible to read the
      contents of a file and its timestamp in a 
      single step. So, the most frequent case of 
      the file would always have this limitation,
      unlike database stored resources.
jakarta-velocity/src/java/org/apache/velocity/runtime/resource/ResourceManager.java

--- ResourceManager.java
+++ ResourceManager.java
@@ -260,6 +260,12 @@
                     try
                     {
                         /*
+                         *  read how old the resource is _before_
+                         *  processing (=>reading) it
+                         */
+                        long howOldItWas = resourceLoader.getLastModified( resource );
+
+                        /*
                          *  read in the fresh stream and parse
                          */
 
@@ -270,8 +276,7 @@
                          *  the modification check counters
                          */
                         
-                        resource.setLastModified( 
-                            resourceLoader.getLastModified( resource ));              
 
+                        resource.setLastModified( howOldItWas );
                     }
                     catch( ResourceNotFoundException rnfe )
                     {
@@ -314,6 +319,7 @@
                 
                 //! Bug this is being run more then once!
                 
+                long howOldItWas = 0;  // Initialize to avoid warnings
                 for (int i = 0; i < resourceLoaders.size(); i++)
                 {
                     resourceLoader = (ResourceLoader) resourceLoaders.get(i);
@@ -322,6 +328,11 @@
                     Runtime.info("Attempting to find " + resourceName + 
                         " with " + resourceLoader.getClassName());
                     
+                    /*
+                     *  read how old the resource is _before_
+                     *  processing (=>reading) it
+                     */
+                    howOldItWas = resourceLoader.getLastModified( resource );
                     if (resource.process())
                         break;
                 }
@@ -332,7 +343,7 @@
                 if (resource.getData() == null)
                     throw new ResourceNotFoundException("Can't find " + resourceName 
+ "!");
                 
-                resource.setLastModified(resourceLoader.getLastModified(resource));
+                resource.setLastModified(howOldItWas);
                 
                 resource.setModificationCheckInterval(
                     resourceLoader.getModificationCheckInterval());

Reply via email to