The list of files belonging to a prototype is now managed by the prototype itself.
The prototype also keeps a checksum over its files which allows it to recognize changes in any of the files quickly and easily.
This commit is contained in:
parent
24dece80bb
commit
f4002ac605
2 changed files with 85 additions and 35 deletions
|
@ -24,6 +24,11 @@ public final class Prototype {
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
Application app;
|
Application app;
|
||||||
|
File directory;
|
||||||
|
|
||||||
|
File [] files;
|
||||||
|
long lastDirectoryListing;
|
||||||
|
long checksum;
|
||||||
|
|
||||||
HashMap code, zippedCode;
|
HashMap code, zippedCode;
|
||||||
HashMap skins, zippedSkins;
|
HashMap skins, zippedSkins;
|
||||||
|
@ -36,7 +41,7 @@ public final class Prototype {
|
||||||
DbMapping dbmap;
|
DbMapping dbmap;
|
||||||
|
|
||||||
// lastCheck is the time the prototype's files were last checked
|
// 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
|
// lastUpdate is the time at which any of the prototype's files were
|
||||||
// found updated the last time
|
// found updated the last time
|
||||||
private long lastUpdate;
|
private long lastUpdate;
|
||||||
|
@ -47,10 +52,11 @@ public final class Prototype {
|
||||||
// as opposed to a Helma objectmodel node object.
|
// as opposed to a Helma objectmodel node object.
|
||||||
boolean isJavaPrototype;
|
boolean isJavaPrototype;
|
||||||
|
|
||||||
public Prototype (String name, Application app) {
|
public Prototype (String name, File dir, Application app) {
|
||||||
// app.logEvent ("Constructing Prototype "+app.getName()+"/"+name);
|
// app.logEvent ("Constructing Prototype "+app.getName()+"/"+name);
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.directory = dir;
|
||||||
|
|
||||||
code = new HashMap ();
|
code = new HashMap ();
|
||||||
zippedCode = new HashMap ();
|
zippedCode = new HashMap ();
|
||||||
|
@ -61,7 +67,7 @@ public final class Prototype {
|
||||||
skinMap = new SkinMap ();
|
skinMap = new SkinMap ();
|
||||||
|
|
||||||
isJavaPrototype = app.isJavaPrototype (name);
|
isJavaPrototype = app.isJavaPrototype (name);
|
||||||
lastUpdate = lastCheck = 0;
|
lastUpdate = lastChecksum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,6 +77,43 @@ public final class Prototype {
|
||||||
return app;
|
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<f.length; i++)
|
||||||
|
c += f[i].lastModified();
|
||||||
|
checksum = c;
|
||||||
|
// System.err.println ("CHECKSUM "+name+": "+(System.currentTimeMillis()-start));
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUpToDate () {
|
||||||
|
return checksum == lastChecksum;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the parent prototype of this prototype, i.e. the prototype this
|
* Set the parent prototype of this prototype, i.e. the prototype this
|
||||||
|
@ -130,17 +173,6 @@ public final class Prototype {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Updatable[] upd = null;
|
|
||||||
public Updatable[] getUpdatables () {
|
|
||||||
if (upd == null) {
|
|
||||||
upd = new Updatable[updatables.size()];
|
|
||||||
int i = 0;
|
|
||||||
for (Iterator it = updatables.values().iterator(); it.hasNext(); ) {
|
|
||||||
upd[i++] = (Updatable) it.next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return upd;
|
|
||||||
} */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the last time any script has been re-read for this prototype.
|
* Get the last time any script has been re-read for this prototype.
|
||||||
|
@ -162,18 +194,20 @@ public final class Prototype {
|
||||||
* Get the time at which this prototype's scripts were checked
|
* Get the time at which this prototype's scripts were checked
|
||||||
* for changes for the last time.
|
* for changes for the last time.
|
||||||
*/
|
*/
|
||||||
public long getLastCheck () {
|
/* public long getLastCheck () {
|
||||||
return lastCheck;
|
return lastCheck;
|
||||||
}
|
} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal that the prototype's scripts have been checked for
|
* Signal that the prototype's scripts have been checked for
|
||||||
* changes.
|
* changes.
|
||||||
*/
|
*/
|
||||||
public void markChecked () {
|
public void markChecked () {
|
||||||
lastCheck = System.currentTimeMillis ();
|
// lastCheck = System.currentTimeMillis ();
|
||||||
|
lastChecksum = checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a clone of this prototype's actions container. Synchronized
|
* Return a clone of this prototype's actions container. Synchronized
|
||||||
* to not return a map in a transient state where it is just being
|
* to not return a map in a transient state where it is just being
|
||||||
|
@ -381,7 +415,7 @@ public final class Prototype {
|
||||||
|
|
||||||
|
|
||||||
private void checkForUpdates () {
|
private void checkForUpdates () {
|
||||||
if (lastCheck < System.currentTimeMillis()- 2000l)
|
if (/* lastCheck < System.currentTimeMillis()- 2000l*/ !isUpToDate())
|
||||||
app.typemgr.updatePrototype (Prototype.this);
|
app.typemgr.updatePrototype (Prototype.this);
|
||||||
if (lastUpdate > lastSkinmapLoad)
|
if (lastUpdate > lastSkinmapLoad)
|
||||||
load ();
|
load ();
|
||||||
|
|
|
@ -24,6 +24,8 @@ public final class TypeManager {
|
||||||
HashMap zipfiles;
|
HashMap zipfiles;
|
||||||
long lastCheck = 0;
|
long lastCheck = 0;
|
||||||
long appDirMod = 0;
|
long appDirMod = 0;
|
||||||
|
// a checksum that changes whenever something in the application files changes.
|
||||||
|
long checksum;
|
||||||
|
|
||||||
// the hopobject prototype
|
// the hopobject prototype
|
||||||
Prototype hopobjectProto;
|
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
|
// loop through zip files to check for updates
|
||||||
for (Iterator it=zipfiles.values ().iterator (); it.hasNext (); ) {
|
for (Iterator it=zipfiles.values ().iterator (); it.hasNext (); ) {
|
||||||
ZippedAppFile zipped = (ZippedAppFile) it.next ();
|
ZippedAppFile zipped = (ZippedAppFile) it.next ();
|
||||||
if (zipped.needsUpdate ()) {
|
if (zipped.needsUpdate ()) {
|
||||||
zipped.update ();
|
zipped.update ();
|
||||||
}
|
}
|
||||||
|
newChecksum += zipped.lastmod;
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop through prototypes and check if type.properties needs updates
|
// 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.
|
// have been created in the previous loop.
|
||||||
for (Iterator i=prototypes.values().iterator(); i.hasNext(); ) {
|
for (Iterator i=prototypes.values().iterator(); i.hasNext(); ) {
|
||||||
Prototype proto = (Prototype) i.next ();
|
Prototype proto = (Prototype) i.next ();
|
||||||
|
// calculate this app's type checksum
|
||||||
|
newChecksum += proto.getChecksum();
|
||||||
// update prototype's type mapping
|
// update prototype's type mapping
|
||||||
DbMapping dbmap = proto.getDbMapping ();
|
DbMapping dbmap = proto.getDbMapping ();
|
||||||
if (dbmap != null && dbmap.needsUpdate ()) {
|
if (dbmap != null && dbmap.needsUpdate ()) {
|
||||||
|
@ -150,7 +158,7 @@ public final class TypeManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
checksum = newChecksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void removeZipFile (String zipname) {
|
protected void removeZipFile (String zipname) {
|
||||||
|
@ -175,6 +183,14 @@ public final class TypeManager {
|
||||||
return true;
|
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
|
* 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
|
* 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).
|
* caller (e.g. ZippedAppFile).
|
||||||
*/
|
*/
|
||||||
public Prototype createPrototype (String typename) {
|
public Prototype createPrototype (String typename) {
|
||||||
|
@ -196,7 +212,7 @@ public final class TypeManager {
|
||||||
* Create a prototype from a directory containing scripts and other stuff
|
* Create a prototype from a directory containing scripts and other stuff
|
||||||
*/
|
*/
|
||||||
public Prototype createPrototype (String typename, File dir) {
|
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
|
// Create and register type properties file
|
||||||
File propfile = new File (dir, "type.properties");
|
File propfile = new File (dir, "type.properties");
|
||||||
SystemProperties props = new SystemProperties (propfile.getAbsolutePath ());
|
SystemProperties props = new SystemProperties (propfile.getAbsolutePath ());
|
||||||
|
@ -224,16 +240,16 @@ public final class TypeManager {
|
||||||
* Update a prototype to the files in the prototype directory.
|
* Update a prototype to the files in the prototype directory.
|
||||||
*/
|
*/
|
||||||
public void updatePrototype (Prototype proto) {
|
public void updatePrototype (Prototype proto) {
|
||||||
if (proto == null)
|
if (proto == null || proto.isUpToDate())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
synchronized (proto) {
|
synchronized (proto) {
|
||||||
// check again because another thread may have checked the
|
// check again because another thread may have checked the
|
||||||
// prototype while we were waiting for access to the synchronized section
|
// prototype while we were waiting for access to the synchronized section
|
||||||
if (System.currentTimeMillis() - proto.getLastCheck() < 1000)
|
/* if (System.currentTimeMillis() - proto.getLastCheck() < 1000)
|
||||||
return;
|
return; */
|
||||||
|
|
||||||
File dir = new File (appDir, proto.getName());
|
File dir = proto.getDirectory ();
|
||||||
HashSet updateSet = null;
|
HashSet updateSet = null;
|
||||||
HashSet createSet = 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
|
// next we check if files have been created or removed since last update
|
||||||
if (proto.getLastCheck() < dir.lastModified ()) {
|
// if (proto.getLastCheck() < dir.lastModified ()) {
|
||||||
String[] list = dir.list();
|
File[] list = proto.getFiles();
|
||||||
for (int i=0; i<list.length; i++) {
|
for (int i=0; i<list.length; i++) {
|
||||||
String fn = list[i];
|
String fn = list[i].getName();
|
||||||
if (!proto.updatables.containsKey (fn)) {
|
if (!proto.updatables.containsKey (fn)) {
|
||||||
if (fn.endsWith (templateExtension) ||
|
if (fn.endsWith (templateExtension) ||
|
||||||
fn.endsWith (scriptExtension) ||
|
fn.endsWith (scriptExtension) ||
|
||||||
|
@ -266,7 +282,7 @@ public final class TypeManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// }
|
||||||
|
|
||||||
// if nothing needs to be updated, mark prototype as checked and return
|
// if nothing needs to be updated, mark prototype as checked and return
|
||||||
if (updateSet == null && createSet == null) {
|
if (updateSet == null && createSet == null) {
|
||||||
|
@ -278,34 +294,34 @@ public final class TypeManager {
|
||||||
if (createSet != null) {
|
if (createSet != null) {
|
||||||
Object[] newFiles = createSet.toArray ();
|
Object[] newFiles = createSet.toArray ();
|
||||||
for (int i=0; i<newFiles.length; i++) {
|
for (int i=0; i<newFiles.length; i++) {
|
||||||
String filename = (String) newFiles[i];
|
File file = (File) newFiles[i];
|
||||||
|
String filename = file.getName ();
|
||||||
int dot = filename.lastIndexOf (".");
|
int dot = filename.lastIndexOf (".");
|
||||||
String tmpname = filename.substring(0, dot);
|
String tmpname = filename.substring(0, dot);
|
||||||
File tmpfile = new File (dir, filename);
|
|
||||||
|
|
||||||
if (filename.endsWith (templateExtension)) {
|
if (filename.endsWith (templateExtension)) {
|
||||||
try {
|
try {
|
||||||
Template t = new Template (tmpfile, tmpname, proto);
|
Template t = new Template (file, tmpname, proto);
|
||||||
proto.addTemplate (t);
|
proto.addTemplate (t);
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
app.logEvent ("Error updating prototype: "+x);
|
app.logEvent ("Error updating prototype: "+x);
|
||||||
}
|
}
|
||||||
} else if (filename.endsWith (scriptExtension)) {
|
} else if (filename.endsWith (scriptExtension)) {
|
||||||
try {
|
try {
|
||||||
FunctionFile ff = new FunctionFile (tmpfile, proto);
|
FunctionFile ff = new FunctionFile (file, proto);
|
||||||
proto.addFunctionFile (ff);
|
proto.addFunctionFile (ff);
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
app.logEvent ("Error updating prototype: "+x);
|
app.logEvent ("Error updating prototype: "+x);
|
||||||
}
|
}
|
||||||
} else if (filename.endsWith (actionExtension)) {
|
} else if (filename.endsWith (actionExtension)) {
|
||||||
try {
|
try {
|
||||||
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
|
ActionFile af = new ActionFile (file, tmpname, proto);
|
||||||
proto.addActionFile (af);
|
proto.addActionFile (af);
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
app.logEvent ("Error updating prototype: "+x);
|
app.logEvent ("Error updating prototype: "+x);
|
||||||
}
|
}
|
||||||
} else if (filename.endsWith (skinExtension)) {
|
} else if (filename.endsWith (skinExtension)) {
|
||||||
SkinFile sf = new SkinFile (tmpfile, tmpname, proto);
|
SkinFile sf = new SkinFile (file, tmpname, proto);
|
||||||
proto.addSkinFile (sf);
|
proto.addSkinFile (sf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue