diff --git a/src/helma/framework/core/Prototype.java b/src/helma/framework/core/Prototype.java index 203927e8..a5815ef7 100644 --- a/src/helma/framework/core/Prototype.java +++ b/src/helma/framework/core/Prototype.java @@ -24,6 +24,11 @@ public final class Prototype { String name; Application app; + File directory; + + File [] files; + long lastDirectoryListing; + long checksum; HashMap code, zippedCode; HashMap skins, zippedSkins; @@ -36,7 +41,7 @@ public final class Prototype { DbMapping dbmap; // lastCheck is the time the prototype's files were last checked - private long lastCheck; + private long lastChecksum; // lastUpdate is the time at which any of the prototype's files were // found updated the last time private long lastUpdate; @@ -47,10 +52,11 @@ public final class Prototype { // as opposed to a Helma objectmodel node object. boolean isJavaPrototype; - public Prototype (String name, Application app) { + public Prototype (String name, File dir, Application app) { // app.logEvent ("Constructing Prototype "+app.getName()+"/"+name); this.app = app; this.name = name; + this.directory = dir; code = new HashMap (); zippedCode = new HashMap (); @@ -61,7 +67,7 @@ public final class Prototype { skinMap = new SkinMap (); isJavaPrototype = app.isJavaPrototype (name); - lastUpdate = lastCheck = 0; + lastUpdate = lastChecksum = 0; } /** @@ -71,6 +77,43 @@ public final class Prototype { return app; } + /** + * Return this prototype's directory. + */ + public File getDirectory () { + return directory; + } + + /** + * Get the list of files in this prototype's directory + */ + public File[] getFiles () { + if (files == null || directory.lastModified() != lastDirectoryListing) { + lastDirectoryListing = directory.lastModified (); + files = directory.listFiles(); + if (files == null) + files = new File[0]; + } + return files; + } + + /** + * Get a checksum over the files in this prototype's directory + */ + public long getChecksum () { + // long start = System.currentTimeMillis(); + File[] f = getFiles (); + long c = 0; + for (int i=0; i lastSkinmapLoad) load (); diff --git a/src/helma/framework/core/TypeManager.java b/src/helma/framework/core/TypeManager.java index 97fd1102..60b329ba 100644 --- a/src/helma/framework/core/TypeManager.java +++ b/src/helma/framework/core/TypeManager.java @@ -24,6 +24,8 @@ public final class TypeManager { HashMap zipfiles; long lastCheck = 0; long appDirMod = 0; + // a checksum that changes whenever something in the application files changes. + long checksum; // the hopobject prototype Prototype hopobjectProto; @@ -123,12 +125,16 @@ public final class TypeManager { } } + // calculate this app's checksum by adding all checksums from all prototypes + long newChecksum = 0; + // loop through zip files to check for updates for (Iterator it=zipfiles.values ().iterator (); it.hasNext (); ) { ZippedAppFile zipped = (ZippedAppFile) it.next (); if (zipped.needsUpdate ()) { zipped.update (); } + newChecksum += zipped.lastmod; } // loop through prototypes and check if type.properties needs updates @@ -136,6 +142,8 @@ public final class TypeManager { // have been created in the previous loop. for (Iterator i=prototypes.values().iterator(); i.hasNext(); ) { Prototype proto = (Prototype) i.next (); + // calculate this app's type checksum + newChecksum += proto.getChecksum(); // update prototype's type mapping DbMapping dbmap = proto.getDbMapping (); if (dbmap != null && dbmap.needsUpdate ()) { @@ -150,7 +158,7 @@ public final class TypeManager { } } } - + checksum = newChecksum; } protected void removeZipFile (String zipname) { @@ -175,6 +183,14 @@ public final class TypeManager { return true; } + /** + * Return a checksum over all files in all prototypes in this application. + * The checksum can be used to find out quickly if any file has changed. + */ + public long getChecksum () { + return checksum; + } + /** * Get a prototype defined for this application */ @@ -184,7 +200,7 @@ public final class TypeManager { /** * Get a prototype, creating it if it doesn't already exist. Note - * that it doesn't create a DbMapping - this is left to the + * that it doesn't create a DbMapping - this is left to the * caller (e.g. ZippedAppFile). */ public Prototype createPrototype (String typename) { @@ -196,7 +212,7 @@ public final class TypeManager { * Create a prototype from a directory containing scripts and other stuff */ public Prototype createPrototype (String typename, File dir) { - Prototype proto = new Prototype (typename, app); + Prototype proto = new Prototype (typename, dir, app); // Create and register type properties file File propfile = new File (dir, "type.properties"); SystemProperties props = new SystemProperties (propfile.getAbsolutePath ()); @@ -224,16 +240,16 @@ public final class TypeManager { * Update a prototype to the files in the prototype directory. */ public void updatePrototype (Prototype proto) { - if (proto == null) + if (proto == null || proto.isUpToDate()) return; synchronized (proto) { // check again because another thread may have checked the // prototype while we were waiting for access to the synchronized section - if (System.currentTimeMillis() - proto.getLastCheck() < 1000) - return; + /* if (System.currentTimeMillis() - proto.getLastCheck() < 1000) + return; */ - File dir = new File (appDir, proto.getName()); + File dir = proto.getDirectory (); HashSet updateSet = null; HashSet createSet = null; @@ -249,10 +265,10 @@ public final class TypeManager { } // next we check if files have been created or removed since last update - if (proto.getLastCheck() < dir.lastModified ()) { - String[] list = dir.list(); + // if (proto.getLastCheck() < dir.lastModified ()) { + File[] list = proto.getFiles(); for (int i=0; i