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; long starttime;
Hashtable sessions; Hashtable sessions;
Hashtable dbMappings;
Hashtable dbSources; Hashtable dbSources;
// internal worker thread for scheduler, session cleanup etc. // internal worker thread for scheduler, session cleanup etc.
@ -224,7 +223,6 @@ public final class Application
} }
sessions = new Hashtable (); sessions = new Hashtable ();
dbMappings = new Hashtable ();
dbSources = new Hashtable (); dbSources = new Hashtable ();
cachenode = new TransientNode ("app"); cachenode = new TransientNode ("app");
@ -281,8 +279,7 @@ public final class Application
p.put ("_children", "collection(user)"); p.put ("_children", "collection(user)");
p.put ("_children.accessname", usernameField); p.put ("_children.accessname", usernameField);
userRootMapping = new DbMapping (this, "__userroot__", p); userRootMapping = new DbMapping (this, "__userroot__", p);
userRootMapping.update ();
rewireDbMappings ();
nmgr = new NodeManager (this, dbDir.getAbsolutePath (), props); nmgr = new NodeManager (this, dbDir.getAbsolutePath (), props);
@ -1144,39 +1141,6 @@ public final class Application
logEvent ("Scheduler for "+name+" exiting"); 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 * 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 * Get the DbMapping associated with a prototype name in this application
*/ */
public DbMapping getDbMapping (String typename) { 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. * Proxy method to get a property from the applications properties.
*/ */

View file

@ -10,13 +10,14 @@ import java.io.*;
import helma.framework.*; import helma.framework.*;
import helma.scripting.*; import helma.scripting.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.db.DbMapping;
import helma.util.Updatable; import helma.util.Updatable;
/** /**
* The Prototype class represents Script prototypes/type defined in a Helma * The Prototype class represents Script prototypes/type defined in a Helma
* application. This class manages a prototypes templates, functions and actions * application. This class manages a prototypes templates, functions and actions
* as well as optional information about the mapping of this type to a * as well as optional information about the mapping of this type to a
* relational database table. * relational database table.
*/ */
@ -32,6 +33,8 @@ public final class Prototype {
final HashMap skins; final HashMap skins;
final HashMap updatables; final HashMap updatables;
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 lastCheck;
// 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
@ -68,7 +71,7 @@ public final class Prototype {
/** /**
* Set the parent prototype of this prototype, i.e. the prototype this * Set the parent prototype of this prototype, i.e. the prototype this
* prototype inherits from. * prototype inherits from.
*/ */
public void setParentPrototype (Prototype parent) { public void setParentPrototype (Prototype parent) {
@ -86,6 +89,14 @@ public final class Prototype {
return parent; return parent;
} }
public void setDbMapping (DbMapping dbmap) {
this.dbmap = dbmap;
}
public DbMapping getDbMapping () {
return dbmap;
}
/** /**
* Get a template defined for this prototype. Templates * Get a template defined for this prototype. Templates
* are files that mix layout and code and were used * are files that mix layout and code and were used

View file

@ -23,7 +23,7 @@ public final class TypeManager {
HashMap prototypes; HashMap prototypes;
HashMap zipfiles; HashMap zipfiles;
long lastCheck = 0; long lastCheck = 0;
boolean rewire; // boolean rewire;
final static String[] standardTypes = {"user", "global", "root", "hopobject"}; final static String[] standardTypes = {"user", "global", "root", "hopobject"};
final static String templateExtension = ".hsp"; final static String templateExtension = ".hsp";
@ -54,6 +54,7 @@ public final class TypeManager {
* compile or evaluate any scripts. * compile or evaluate any scripts.
*/ */
public void createPrototypes () { public void createPrototypes () {
// loop through directories and create prototypes
checkFiles (); checkFiles ();
// check if standard prototypes have been created // check if standard prototypes have been created
// if not, create them. // if not, create them.
@ -62,9 +63,22 @@ public final class TypeManager {
if (prototypes.get (pname) == null) { if (prototypes.get (pname) == null) {
Prototype proto = new Prototype (pname, app); Prototype proto = new Prototype (pname, app);
registerPrototype (pname, new File (appDir, pname), proto); 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 () { public void checkFiles () {
// long now = System.currentTimeMillis (); // long now = System.currentTimeMillis ();
// System.out.print ("checking "+Thread.currentThread ()); // System.out.print ("checking prototypes for "+app);
File[] list = appDir.listFiles (); File[] list = appDir.listFiles ();
if (list == null) if (list == null)
throw new RuntimeException ("Can't read app directory "+appDir+" - check permissions"); throw new RuntimeException ("Can't read app directory "+appDir+" - check permissions");
for (int i=0; i<list.length; i++) { for (int i=0; i<list.length; i++) {
String filename = list[i].getName (); String filename = list[i].getName ();
Prototype proto = getPrototype (filename); Prototype proto = getPrototype (filename);
if (proto != null) { // if prototype doesn't exist, create it
// check if existing prototype needs update if (proto == null) {
// app.logEvent (protoDir.lastModified ());
// updatePrototype (filename, list[i], proto);
} else if (list[i].isDirectory () && isValidTypeName (filename)) {
// leave out ".." and other directories that contain "." // leave out ".." and other directories that contain "."
// create new prototype if (list[i].isDirectory () && isValidTypeName (filename)) {
proto = new Prototype (filename, app); // create new prototype
registerPrototype (filename, list[i], proto); proto = new Prototype (filename, app);
prototypes.put (filename, proto); registerPrototype (filename, list[i], proto);
// give logger thread a chance to tell what's going on // give logger thread a chance to tell what's going on
// Thread.yield(); // Thread.yield();
} else if (filename.toLowerCase().endsWith (".zip") && !list[i].isDirectory ()) { } else if (filename.toLowerCase().endsWith (".zip") && !list[i].isDirectory ()) {
ZippedAppFile zipped = (ZippedAppFile) zipfiles.get (filename); ZippedAppFile zipped = (ZippedAppFile) zipfiles.get (filename);
if (zipped == null) { if (zipped == null) {
zipped = new ZippedAppFile (list[i], app); zipped = new ZippedAppFile (list[i], app);
zipfiles.put (filename, zipped); 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) { public Prototype createPrototype (String typename) {
Prototype p = getPrototype (typename); Prototype p = getPrototype (typename);
@ -171,9 +192,13 @@ public final class TypeManager {
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 ());
DbMapping dbmap = new DbMapping (app, name, props); 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]; String fn = list[i];
if (!proto.updatables.containsKey (fn)) { if (!proto.updatables.containsKey (fn)) {
if (fn.endsWith (templateExtension) || fn.endsWith (scriptExtension) || if (fn.endsWith (templateExtension) || fn.endsWith (scriptExtension) ||
fn.endsWith (actionExtension) || fn.endsWith (skinExtension) || fn.endsWith (actionExtension) || fn.endsWith (skinExtension) ||
"type.properties".equalsIgnoreCase (fn)) { "type.properties".equalsIgnoreCase (fn)) {
needsUpdate = true; needsUpdate = true;
// updatables.add ("[new:"+proto.getName()+"/"+fn+"]"); // updatables.add ("[new:"+proto.getName()+"/"+fn+"]");
} }
@ -299,17 +324,13 @@ public final class TypeManager {
for (Iterator i = updatables.iterator(); i.hasNext(); ) { for (Iterator i = updatables.iterator(); i.hasNext(); ) {
Updatable upd = (Updatable) i.next(); Updatable upd = (Updatable) i.next();
if (upd.needsUpdate ()) { try {
if (upd instanceof DbMapping) upd.update ();
rewire = true; } catch (Exception x) {
try { if (upd instanceof DbMapping)
upd.update (); app.logEvent ("Error updating db mapping for type "+proto.getName()+": "+x);
} catch (Exception x) { else
if (upd instanceof DbMapping) app.logEvent ("Error updating "+upd+" of prototye type "+proto.getName()+": "+x);
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 // DbMapping doesn't exist, we still need to create one
SystemProperties props = new SystemProperties (); SystemProperties props = new SystemProperties ();
// DbMapping does its own registering, just construct it. // 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) { } catch (Throwable x) {

View file

@ -119,9 +119,6 @@ public final class DbMapping implements Updatable {
idField = null; idField = null;
this.props = props; this.props = props;
update ();
app.putDbMapping (typename, this);
} }
/** /**
@ -139,13 +136,6 @@ public final class DbMapping implements Updatable {
*/ */
public synchronized void update () { 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"); table = props.getProperty ("_table");
idgen = props.getProperty ("_idgen"); idgen = props.getProperty ("_idgen");
// see if there is a field which specifies the prototype of objects, if different prototypes // see if there is a field which specifies the prototype of objects, if different prototypes
@ -170,32 +160,27 @@ public final class DbMapping implements Updatable {
nameField = props.getProperty ("_name"); nameField = props.getProperty ("_name");
protoField = props.getProperty ("_prototype"); protoField = props.getProperty ("_prototype");
String parentMapping = props.getProperty ("_parent"); String parentSpec = props.getProperty ("_parent");
if (parentMapping != null) { if (parentSpec != null) {
// comma-separated list of properties to be used as parent // 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()]; parent = new ParentInfo[st.countTokens()];
for (int i=0; i<parent.length; i++) for (int i=0; i<parent.length; i++)
parent[i] = new ParentInfo (st.nextToken().trim()); parent[i] = new ParentInfo (st.nextToken().trim());
} else } else {
parent = null; parent = null;
}
lastTypeChange = props.lastModified (); lastTypeChange = props.lastModified ();
// set the cached schema & keydef to null so it's rebuilt the next time around // set the cached schema & keydef to null so it's rebuilt the next time around
schema = null; schema = null;
keydef = 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) { if (extendsProto != null) {
parentMapping = app.getDbMapping (extendsProto); parentMapping = app.getDbMapping (extendsProto);
} }
// if (table != null && source != null) { // if (table != null && source != null) {
// app.logEvent ("set data source for "+typename+" to "+source); // app.logEvent ("set data source for "+typename+" to "+source);
HashMap p2d = new HashMap (); HashMap p2d = new HashMap ();

View file

@ -873,7 +873,7 @@ public final class NodeManager {
Node node = null; Node node = null;
DbMapping dbm = app.getDbMapping (key.getStorageName ()); DbMapping dbm = app.getDbMapping (key.getStorageName ());
String kstr = key.getID (); String kstr = key.getID ();
if (dbm == null || !dbm.isRelational ()) { if (dbm == null || !dbm.isRelational ()) {
node = (Node)db.getNode (txn, kstr); node = (Node)db.getNode (txn, kstr);
node.nmgr = safe; node.nmgr = safe;
@ -881,7 +881,7 @@ public final class NodeManager {
node.setDbMapping (dbm); node.setDbMapping (dbm);
} else { } else {
String idfield =dbm.getIDField (); String idfield =dbm.getIDField ();
TableDataSet tds = null; TableDataSet tds = null;
try { try {
tds = new TableDataSet (dbm.getConnection (), dbm.getSchema (), dbm.getKeyDef ()); tds = new TableDataSet (dbm.getConnection (), dbm.getSchema (), dbm.getKeyDef ());

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 // if this relation defines a virtual node, we need to provide a DbMapping for these virtual nodes
DbMapping virtualMapping; DbMapping virtualMapping;
Relation virtualRelation;
Relation groupRelation;
String propName; String propName;
String columnName; String columnName;
@ -150,6 +147,14 @@ public final class Relation {
constraints = new Constraint[newConstraints.size()]; constraints = new Constraint[newConstraints.size()];
newConstraints.copyInto (constraints); 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.groupbyprototype = groupbyprototype;
vr.order = order; vr.order = order;
vr.filter = filter; vr.filter = filter;
vr.maxSize = maxSize;
vr.constraints = constraints; vr.constraints = constraints;
vr.aggressiveLoading = aggressiveLoading; vr.aggressiveLoading = aggressiveLoading;
vr.aggressiveCaching = aggressiveCaching; vr.aggressiveCaching = aggressiveCaching;
@ -319,6 +325,7 @@ public final class Relation {
vr.groupbyprototype = groupbyprototype; vr.groupbyprototype = groupbyprototype;
vr.order = order; vr.order = order;
vr.filter = filter; vr.filter = filter;
vr.maxSize = maxSize;
vr.constraints = constraints; vr.constraints = constraints;
return vr; return vr;
} }