Big patch to clean up checking type.properties files. Changes in type.properties are

now reflected on existing collection objects (aka virtual subnodes).

DbMappings are no longer managed by the application. Instead they're now held by
the prototype they belong to.
This commit is contained in:
hns 2002-09-06 19:42:32 +00:00
parent 64b766ea35
commit df0639c02f
7 changed files with 103 additions and 117 deletions

View file

@ -74,7 +74,6 @@ public final class Application
long starttime;
Hashtable sessions;
Hashtable dbMappings;
Hashtable dbSources;
// internal worker thread for scheduler, session cleanup etc.
@ -224,7 +223,6 @@ public final class Application
}
sessions = new Hashtable ();
dbMappings = new Hashtable ();
dbSources = new Hashtable ();
cachenode = new TransientNode ("app");
@ -281,8 +279,7 @@ public final class Application
p.put ("_children", "collection(user)");
p.put ("_children.accessname", usernameField);
userRootMapping = new DbMapping (this, "__userroot__", p);
rewireDbMappings ();
userRootMapping.update ();
nmgr = new NodeManager (this, dbDir.getAbsolutePath (), props);
@ -1144,39 +1141,6 @@ public final class Application
logEvent ("Scheduler for "+name+" exiting");
}
/**
* This method is called after the type.properties files are read on all prototypes, or after one
* or more of the type properties have been re-read after an update, to let the DbMappings reestablish
* the relations among them according to their mappings.
*/
public void rewireDbMappings () {
for (Enumeration e=dbMappings.elements(); e.hasMoreElements(); ) {
try {
DbMapping m = (DbMapping) e.nextElement ();
m.rewire ();
String typename = m.getTypeName ();
// set prototype hierarchy
if (!"hopobject".equalsIgnoreCase (typename) && !"global".equalsIgnoreCase (typename)) {
Prototype proto = (Prototype) typemgr.prototypes.get (typename);
if (proto != null) {
String protoname = m.getExtends ();
// only use hopobject prototype if we're scripting HopObjects, not
// java objects.
boolean isjava = isJavaPrototype (typename);
if (protoname == null && !isjava)
protoname = "hopobject";
Prototype parentProto = (Prototype) typemgr.prototypes.get (protoname);
if (parentProto == null && !isjava)
parentProto = (Prototype) typemgr.prototypes.get ("hopobject");
if (parentProto != null)
proto.setParentPrototype (parentProto);
}
}
} catch (Exception x) {
logEvent ("Error rewiring DbMappings: "+x);
}
}
}
/**
* Check whether a prototype is for scripting a java class, i.e. if there's an entry
@ -1230,15 +1194,13 @@ public final class Application
* Get the DbMapping associated with a prototype name in this application
*/
public DbMapping getDbMapping (String typename) {
return typename == null ? null : (DbMapping) dbMappings.get (typename);
Prototype proto = typemgr.getPrototype (typename);
if (proto == null)
return null;
return proto.getDbMapping ();
}
/**
* Associate a DbMapping object with a prototype name for this application.
*/
public void putDbMapping (String typename, DbMapping dbmap) {
dbMappings.put (typename, dbmap);
}
/**
* Proxy method to get a property from the applications properties.
*/

View file

@ -10,6 +10,7 @@ import java.io.*;
import helma.framework.*;
import helma.scripting.*;
import helma.objectmodel.*;
import helma.objectmodel.db.DbMapping;
import helma.util.Updatable;
@ -32,6 +33,8 @@ public final class Prototype {
final HashMap skins;
final HashMap updatables;
DbMapping dbmap;
// lastCheck is the time the prototype's files were last checked
private long lastCheck;
// lastUpdate is the time at which any of the prototype's files were
@ -86,6 +89,14 @@ public final class Prototype {
return parent;
}
public void setDbMapping (DbMapping dbmap) {
this.dbmap = dbmap;
}
public DbMapping getDbMapping () {
return dbmap;
}
/**
* Get a template defined for this prototype. Templates
* are files that mix layout and code and were used

View file

@ -23,7 +23,7 @@ public final class TypeManager {
HashMap prototypes;
HashMap zipfiles;
long lastCheck = 0;
boolean rewire;
// boolean rewire;
final static String[] standardTypes = {"user", "global", "root", "hopobject"};
final static String templateExtension = ".hsp";
@ -54,6 +54,7 @@ public final class TypeManager {
* compile or evaluate any scripts.
*/
public void createPrototypes () {
// loop through directories and create prototypes
checkFiles ();
// check if standard prototypes have been created
// if not, create them.
@ -62,9 +63,22 @@ public final class TypeManager {
if (prototypes.get (pname) == null) {
Prototype proto = new Prototype (pname, app);
registerPrototype (pname, new File (appDir, pname), proto);
prototypes.put (pname, proto);
}
}
Prototype hobjectProto = getPrototype ("hopobject");
// loop through freshly created prototypes and rewire them,
// i.e. establish connections between them (inherit, collection etc.)
for (Iterator i = prototypes.values().iterator(); i.hasNext(); ) {
Prototype proto = (Prototype) i.next();
DbMapping dbm = proto.getDbMapping ();
dbm.update ();
// set parent prototype
String parentName = dbm.getExtends ();
if (parentName == null)
proto.setParentPrototype (hobjectProto);
else
proto.setParentPrototype (getPrototype (parentName));
}
}
@ -82,34 +96,44 @@ public final class TypeManager {
}
/**
* Run through application's prototype directories and check if anything has been updated.
* Run through application's prototype directories and check if
* there are any prototypes to be created.
*/
public void checkFiles () {
// long now = System.currentTimeMillis ();
// System.out.print ("checking "+Thread.currentThread ());
// System.out.print ("checking prototypes for "+app);
File[] list = appDir.listFiles ();
if (list == null)
throw new RuntimeException ("Can't read app directory "+appDir+" - check permissions");
for (int i=0; i<list.length; i++) {
String filename = list[i].getName ();
Prototype proto = getPrototype (filename);
if (proto != null) {
// check if existing prototype needs update
// app.logEvent (protoDir.lastModified ());
// updatePrototype (filename, list[i], proto);
} else if (list[i].isDirectory () && isValidTypeName (filename)) {
// if prototype doesn't exist, create it
if (proto == null) {
// leave out ".." and other directories that contain "."
// create new prototype
proto = new Prototype (filename, app);
registerPrototype (filename, list[i], proto);
prototypes.put (filename, proto);
// give logger thread a chance to tell what's going on
// Thread.yield();
} else if (filename.toLowerCase().endsWith (".zip") && !list[i].isDirectory ()) {
ZippedAppFile zipped = (ZippedAppFile) zipfiles.get (filename);
if (zipped == null) {
zipped = new ZippedAppFile (list[i], app);
zipfiles.put (filename, zipped);
if (list[i].isDirectory () && isValidTypeName (filename)) {
// create new prototype
proto = new Prototype (filename, app);
registerPrototype (filename, list[i], proto);
// give logger thread a chance to tell what's going on
// Thread.yield();
} else if (filename.toLowerCase().endsWith (".zip") && !list[i].isDirectory ()) {
ZippedAppFile zipped = (ZippedAppFile) zipfiles.get (filename);
if (zipped == null) {
zipped = new ZippedAppFile (list[i], app);
zipfiles.put (filename, zipped);
}
}
} else {
// update prototype's type mapping
DbMapping dbmap = proto.getDbMapping ();
if (dbmap != null && dbmap.needsUpdate ()) {
dbmap.update ();
// set parent prototype, in case it has changed.
String parentName = dbmap.getExtends ();
if (parentName == null)
parentName = "hopobject";
proto.setParentPrototype (getPrototype (parentName));
}
}
}
@ -122,11 +146,6 @@ public final class TypeManager {
}
}
if (rewire) {
// there have been changes in the DbMappings
app.rewireDbMappings ();
rewire = false;
}
}
@ -148,7 +167,9 @@ public final class TypeManager {
}
/**
* Get a prototype, creating it if id doesn't already exist
* Get a prototype, creating it if it doesn't already exist. Note
* that it doesn't create a DbMapping - this is left to the
* caller (e.g. ZippedAppFile).
*/
public Prototype createPrototype (String typename) {
Prototype p = getPrototype (typename);
@ -171,9 +192,13 @@ public final class TypeManager {
File propfile = new File (dir, "type.properties");
SystemProperties props = new SystemProperties (propfile.getAbsolutePath ());
DbMapping dbmap = new DbMapping (app, name, props);
proto.updatables.put ("type.properties", dbmap);
// we don't need to put the DbMapping into proto.updatables, because
// dbmappings are checked separately in checkFiles for each request
// proto.updatables.put ("type.properties", dbmap);
proto.setDbMapping (dbmap);
// app.scriptingEngine.updatePrototype (proto);
// put the prototype into our map
prototypes.put (name, proto);
}
@ -226,8 +251,8 @@ public final class TypeManager {
String fn = list[i];
if (!proto.updatables.containsKey (fn)) {
if (fn.endsWith (templateExtension) || fn.endsWith (scriptExtension) ||
fn.endsWith (actionExtension) || fn.endsWith (skinExtension) ||
"type.properties".equalsIgnoreCase (fn)) {
fn.endsWith (actionExtension) || fn.endsWith (skinExtension) ||
"type.properties".equalsIgnoreCase (fn)) {
needsUpdate = true;
// updatables.add ("[new:"+proto.getName()+"/"+fn+"]");
}
@ -299,17 +324,13 @@ public final class TypeManager {
for (Iterator i = updatables.iterator(); i.hasNext(); ) {
Updatable upd = (Updatable) i.next();
if (upd.needsUpdate ()) {
if (upd instanceof DbMapping)
rewire = true;
try {
upd.update ();
} catch (Exception x) {
if (upd instanceof DbMapping)
app.logEvent ("Error updating db mapping for type "+proto.getName()+": "+x);
else
app.logEvent ("Error updating "+upd+" of prototye type "+proto.getName()+": "+x);
}
try {
upd.update ();
} catch (Exception x) {
if (upd instanceof DbMapping)
app.logEvent ("Error updating db mapping for type "+proto.getName()+": "+x);
else
app.logEvent ("Error updating "+upd+" of prototye type "+proto.getName()+": "+x);
}
}
}

View file

@ -118,7 +118,7 @@ public class ZippedAppFile implements Updatable {
// DbMapping doesn't exist, we still need to create one
SystemProperties props = new SystemProperties ();
// DbMapping does its own registering, just construct it.
new DbMapping (app, proto.getName (), props);
proto.setDbMapping (new DbMapping (app, proto.getName (), props));
}
}
} catch (Throwable x) {

View file

@ -119,9 +119,6 @@ public final class DbMapping implements Updatable {
idField = null;
this.props = props;
update ();
app.putDbMapping (typename, this);
}
/**
@ -139,13 +136,6 @@ public final class DbMapping implements Updatable {
*/
public synchronized void update () {
// determin file format version of type.properties file
/* String versionInfo = props.getProperty ("_version");
if ("1.2".equals (versionInfo))
version = 1;
else
version = 0; */
table = props.getProperty ("_table");
idgen = props.getProperty ("_idgen");
// see if there is a field which specifies the prototype of objects, if different prototypes
@ -171,27 +161,22 @@ public final class DbMapping implements Updatable {
protoField = props.getProperty ("_prototype");
String parentMapping = props.getProperty ("_parent");
if (parentMapping != null) {
String parentSpec = props.getProperty ("_parent");
if (parentSpec != null) {
// comma-separated list of properties to be used as parent
StringTokenizer st = new StringTokenizer (parentMapping, ",;");
StringTokenizer st = new StringTokenizer (parentSpec, ",;");
parent = new ParentInfo[st.countTokens()];
for (int i=0; i<parent.length; i++)
parent[i] = new ParentInfo (st.nextToken().trim());
} else
} else {
parent = null;
}
lastTypeChange = props.lastModified ();
// set the cached schema & keydef to null so it's rebuilt the next time around
schema = null;
keydef = null;
}
/**
* This is the second part of the property reading process, called after the first part has been
* completed on all other mappings in this application
*/
public synchronized void rewire () {
if (extendsProto != null) {
parentMapping = app.getDbMapping (extendsProto);
}

View file

@ -38,9 +38,6 @@ public final class Relation {
// if this relation defines a virtual node, we need to provide a DbMapping for these virtual nodes
DbMapping virtualMapping;
Relation virtualRelation;
Relation groupRelation;
String propName;
String columnName;
@ -150,6 +147,14 @@ public final class Relation {
constraints = new Constraint[newConstraints.size()];
newConstraints.copyInto (constraints);
// if DbMapping for virtual nodes has already been created,
// update its subnode relation.
// FIXME: needs to be synchronized?
if (virtualMapping != null) {
virtualMapping.lastTypeChange = ownType.lastTypeChange;
virtualMapping.subnodesRel = getVirtualSubnodeRelation ();
virtualMapping.propertiesRel = getVirtualPropertyRelation ();
}
}
}
@ -301,6 +306,7 @@ public final class Relation {
vr.groupbyprototype = groupbyprototype;
vr.order = order;
vr.filter = filter;
vr.maxSize = maxSize;
vr.constraints = constraints;
vr.aggressiveLoading = aggressiveLoading;
vr.aggressiveCaching = aggressiveCaching;
@ -319,6 +325,7 @@ public final class Relation {
vr.groupbyprototype = groupbyprototype;
vr.order = order;
vr.filter = filter;
vr.maxSize = maxSize;
vr.constraints = constraints;
return vr;
}