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:
parent
64b766ea35
commit
df0639c02f
7 changed files with 103 additions and 117 deletions
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,6 +10,7 @@ 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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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,27 +96,25 @@ 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 "."
|
||||||
|
if (list[i].isDirectory () && isValidTypeName (filename)) {
|
||||||
// create new prototype
|
// create new prototype
|
||||||
proto = new Prototype (filename, app);
|
proto = new Prototype (filename, app);
|
||||||
registerPrototype (filename, list[i], proto);
|
registerPrototype (filename, list[i], proto);
|
||||||
prototypes.put (filename, 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 ()) {
|
||||||
|
@ -112,6 +124,18 @@ public final class TypeManager {
|
||||||
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop through zip files to check for updates
|
// loop through zip files to check for updates
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -299,9 +324,6 @@ 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 ()) {
|
|
||||||
if (upd instanceof DbMapping)
|
|
||||||
rewire = true;
|
|
||||||
try {
|
try {
|
||||||
upd.update ();
|
upd.update ();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
|
@ -312,7 +334,6 @@ public final class TypeManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// mark prototype as checked and updated.
|
// mark prototype as checked and updated.
|
||||||
proto.markChecked ();
|
proto.markChecked ();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
@ -171,27 +161,22 @@ public final class DbMapping implements Updatable {
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue