Merging changes from helma_1_2_3
This commit is contained in:
parent
ed15173b8c
commit
c25ffcf69d
17 changed files with 940 additions and 182 deletions
|
@ -8,7 +8,7 @@
|
|||
<target name="init">
|
||||
<property name="Name" value="helma"/>
|
||||
<property name="year" value="1998-${year}"/>
|
||||
<property name="version" value="1.2.2"/>
|
||||
<property name="version" value="1.2.3"/>
|
||||
<property name="project" value="helma"/>
|
||||
<property name="build.compiler" value="classic"/>
|
||||
|
||||
|
@ -246,7 +246,7 @@
|
|||
<cvs cvsRoot="${cvs.root.apps}" command="export" tag="HEAD" package="base" dest="${build.work}/apps" />
|
||||
<cvs cvsRoot="${cvs.root.apps}" command="export" tag="HEAD" package="bloggerapi" dest="${build.work}/apps" />
|
||||
<cvs cvsRoot="${cvs.root.apps}" command="export" tag="HEAD" package="himp" dest="${build.work}/apps" />
|
||||
<cvs cvsRoot="${cvs.root.apps}" command="export" tag="HEAD" package="hopblog" dest="${build.work}/apps" />
|
||||
<cvs cvsRoot="${cvs.root.apps}" command="export" tag="HEAD" package="gong" dest="${build.work}/apps" />
|
||||
<cvs cvsRoot="${cvs.root.apps}" command="export" tag="HEAD" package="lillebror" dest="${build.work}/apps" />
|
||||
|
||||
<antcall target="package-manage" />
|
||||
|
@ -258,7 +258,7 @@ base
|
|||
base.mountpoint = /
|
||||
bloggerapi
|
||||
himp
|
||||
hopblog
|
||||
gong
|
||||
lillebror
|
||||
manage
|
||||
</echo>
|
||||
|
|
|
@ -84,20 +84,25 @@ public class DocPrototype extends DocDirElement {
|
|||
File f = new File (location.getAbsolutePath (), arr[i]);
|
||||
if (f.isDirectory ())
|
||||
continue;
|
||||
if (arr[i].endsWith (".skin")) {
|
||||
addChild (DocSkin.newInstance (f, this));
|
||||
} else if (arr[i].endsWith (".properties")) {
|
||||
continue;
|
||||
} else if (arr[i].endsWith (".hac")) {
|
||||
addChild (DocFunction.newAction (f, this));
|
||||
} else if (arr[i].endsWith (".hsp")) {
|
||||
addChild (DocFunction.newTemplate (f, this));
|
||||
} else if (arr[i].endsWith (".js")) {
|
||||
DocElement[] elements = DocFunction.newFunctions (f, this);
|
||||
for (int j=0; j<elements.length; j++) {
|
||||
addChild (elements[j]);
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (arr[i].endsWith (".skin")) {
|
||||
addChild (DocSkin.newInstance (f, this));
|
||||
} else if (arr[i].endsWith (".properties")) {
|
||||
continue;
|
||||
} else if (arr[i].endsWith (".hac")) {
|
||||
addChild (DocFunction.newAction (f, this));
|
||||
} else if (arr[i].endsWith (".hsp")) {
|
||||
addChild (DocFunction.newTemplate (f, this));
|
||||
} else if (arr[i].endsWith (".js")) {
|
||||
DocElement[] elements = DocFunction.newFunctions (f, this);
|
||||
for (int j=0; j<elements.length; j++) {
|
||||
addChild (elements[j]);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.out.println ("couldn't parse file " + f.getAbsolutePath () + ": " + ex.toString ());
|
||||
ex.printStackTrace ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -358,8 +358,7 @@ public final class ResponseTrans implements Externalizable {
|
|||
}
|
||||
}
|
||||
// if etag is not set, calc MD5 digest and check it
|
||||
if (etag == null && lastModified == -1 &&
|
||||
redir == null && cache && error == null) try {
|
||||
if (etag == null && lastModified == -1 && redir == null) try {
|
||||
digest = MessageDigest.getInstance("MD5");
|
||||
// if (contentType != null)
|
||||
// digest.update (contentType.getBytes());
|
||||
|
|
|
@ -73,6 +73,9 @@ public final class Application implements IPathElement, Runnable {
|
|||
Hashtable sessions;
|
||||
Hashtable dbSources;
|
||||
|
||||
// map of app modules reflected at app.modules
|
||||
Hashtable modules;
|
||||
|
||||
// internal worker thread for scheduler, session cleanup etc.
|
||||
Thread worker;
|
||||
long requestTimeout = 60000; // 60 seconds for request timeout.
|
||||
|
@ -207,6 +210,7 @@ public final class Application implements IPathElement, Runnable {
|
|||
|
||||
sessions = new Hashtable ();
|
||||
dbSources = new Hashtable ();
|
||||
modules = new Hashtable ();
|
||||
|
||||
cachenode = new TransientNode ("app");
|
||||
}
|
||||
|
@ -215,8 +219,6 @@ public final class Application implements IPathElement, Runnable {
|
|||
* Get the application ready to run, initializing the evaluators and type manager.
|
||||
*/
|
||||
public void init () throws DatabaseException, ScriptingException, MalformedURLException {
|
||||
// scriptingEngine = new helma.scripting.fesi.FesiScriptingEnvironment ();
|
||||
// scriptingEngine.init (this, props);
|
||||
|
||||
Vector extensions = Server.getServer ().getExtensions ();
|
||||
for (int i=0; i<extensions.size(); i++) {
|
||||
|
|
|
@ -120,15 +120,19 @@ public class ApplicationBean implements Serializable {
|
|||
// getter methods for readonly properties of this application
|
||||
|
||||
public int getcacheusage () {
|
||||
return app.getCacheUsage ();
|
||||
return app.getCacheUsage ();
|
||||
}
|
||||
|
||||
public INode getdata() {
|
||||
return app.getCacheNode ();
|
||||
}
|
||||
|
||||
public Map getmodules() {
|
||||
return app.modules;
|
||||
}
|
||||
|
||||
public String getdir () {
|
||||
return app.getAppDir ().getAbsolutePath ();
|
||||
return app.getAppDir ().getAbsolutePath ();
|
||||
}
|
||||
|
||||
public Date getupSince () {
|
||||
|
|
|
@ -25,7 +25,7 @@ public final class Prototype {
|
|||
String name;
|
||||
Application app;
|
||||
File directory;
|
||||
|
||||
|
||||
File [] files;
|
||||
long lastDirectoryListing;
|
||||
long checksum;
|
||||
|
@ -133,6 +133,26 @@ public final class Prototype {
|
|||
public Prototype getParentPrototype () {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given prototype is within this prototype's parent chain.
|
||||
*/
|
||||
public final boolean isInstanceOf (String pname) {
|
||||
if (name.equals (pname))
|
||||
return true;
|
||||
if (parent != null && !"hopobject".equalsIgnoreCase (parent.getName()))
|
||||
return parent.isInstanceOf (pname);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an object as handler for this prototype and all our parent prototypes.
|
||||
*/
|
||||
public final void addToHandlerMap (Map handlers, Object obj) {
|
||||
if (parent != null && !"hopobject".equalsIgnoreCase (parent.getName()))
|
||||
parent.addToHandlerMap (handlers, obj);
|
||||
handlers.put (name, obj);
|
||||
}
|
||||
|
||||
public void setDbMapping (DbMapping dbmap) {
|
||||
this.dbmap = dbmap;
|
||||
|
|
|
@ -212,9 +212,9 @@ public final class RequestEvaluator implements Runnable {
|
|||
if (currentElement != null) {
|
||||
// add to requestPath array
|
||||
requestPath.add (currentElement);
|
||||
String protoName = app.getPrototypeName (currentElement);
|
||||
if (protoName != null)
|
||||
macroHandlers.put (protoName, currentElement);
|
||||
Prototype proto = app.getPrototype (currentElement);
|
||||
if (proto != null)
|
||||
proto.addToHandlerMap (macroHandlers, currentElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -347,10 +347,11 @@ public final class Skin {
|
|||
// was called with this object - check it or its parents for matching prototype
|
||||
if (!handler.equals ("this") && !handler.equals (app.getPrototypeName (thisObject))) {
|
||||
// the handler object is not what we want
|
||||
Object n = app.getParentElement (thisObject);
|
||||
Object n = thisObject;
|
||||
// walk down parent chain to find handler object
|
||||
while (n != null) {
|
||||
if (handler.equals (app.getPrototypeName (n))) {
|
||||
Prototype proto = app.getPrototype (n);
|
||||
if (proto != null && proto.isInstanceOf (handler)) {
|
||||
handlerObject = n;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import org.apache.xmlrpc.*;
|
|||
|
||||
public class Server implements IPathElement, Runnable {
|
||||
|
||||
public static final String version = "1.2.2 (2003/02/04)";
|
||||
public static final String version = "1.2.3 RC1 (2003/03/05)";
|
||||
public final long starttime;
|
||||
|
||||
// if true we only accept RMI and XML-RPC connections from
|
||||
|
|
|
@ -7,6 +7,7 @@ import helma.framework.core.Application;
|
|||
import helma.util.Updatable;
|
||||
import helma.util.SystemProperties;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.StringTokenizer;
|
||||
|
@ -28,15 +29,15 @@ public final class DbMapping implements Updatable {
|
|||
// properties from where the mapping is read
|
||||
SystemProperties props;
|
||||
|
||||
// name of data source to which this mapping writes
|
||||
DbSource source;
|
||||
// name of data dbSource to which this mapping writes
|
||||
DbSource dbSource;
|
||||
// name of datasource
|
||||
String sourceName;
|
||||
String dbSourceName;
|
||||
// name of db table
|
||||
String table;
|
||||
String tableName;
|
||||
|
||||
// list of properties to try for parent
|
||||
ParentInfo[] parent;
|
||||
ParentInfo[] parentInfo;
|
||||
|
||||
// Relations describing subnodes and properties.
|
||||
Relation subRelation;
|
||||
|
@ -101,7 +102,7 @@ public final class DbMapping implements Updatable {
|
|||
prop2db = new HashMap ();
|
||||
db2prop = new HashMap ();
|
||||
|
||||
parent = null;
|
||||
parentInfo = null;
|
||||
|
||||
idField = null;
|
||||
}
|
||||
|
@ -123,7 +124,7 @@ public final class DbMapping implements Updatable {
|
|||
|
||||
columnMap = new HashMap ();
|
||||
|
||||
parent = null;
|
||||
parentInfo = null;
|
||||
|
||||
idField = null;
|
||||
|
||||
|
@ -145,7 +146,7 @@ public final class DbMapping implements Updatable {
|
|||
*/
|
||||
public synchronized void update () {
|
||||
// read in properties
|
||||
table = props.getProperty ("_table");
|
||||
tableName = props.getProperty ("_table");
|
||||
idgen = props.getProperty ("_idgen");
|
||||
// see if there is a field which specifies the prototype of objects, if different prototypes
|
||||
// can be stored in this table
|
||||
|
@ -153,17 +154,17 @@ public final class DbMapping implements Updatable {
|
|||
// see if this prototype extends (inherits from) any other prototype
|
||||
extendsProto = props.getProperty ("_extends");
|
||||
|
||||
sourceName = props.getProperty ("_db");
|
||||
if (sourceName != null) {
|
||||
source = app.getDbSource (sourceName);
|
||||
if (source == null) {
|
||||
app.logEvent ("*** Data Source for prototype "+typename+" does not exist: "+sourceName);
|
||||
dbSourceName = props.getProperty ("_db");
|
||||
if (dbSourceName != null) {
|
||||
dbSource = app.getDbSource (dbSourceName);
|
||||
if (dbSource == null) {
|
||||
app.logEvent ("*** Data Source for prototype "+typename+" does not exist: "+dbSourceName);
|
||||
app.logEvent ("*** accessing or storing a "+typename+" object will cause an error.");
|
||||
} else if (table == null) {
|
||||
} else if (tableName == null) {
|
||||
app.logEvent ("*** No table name specified for prototype "+typename);
|
||||
app.logEvent ("*** accessing or storing a "+typename+" object will cause an error.");
|
||||
// mark mapping as invalid by nulling the source field
|
||||
source = null;
|
||||
// mark mapping as invalid by nulling the dbSource field
|
||||
dbSource = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,11 +180,11 @@ public final class DbMapping implements Updatable {
|
|||
if (parentSpec != null) {
|
||||
// comma-separated list of properties to be used as parent
|
||||
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());
|
||||
parentInfo = new ParentInfo[st.countTokens()];
|
||||
for (int i=0; i<parentInfo.length; i++)
|
||||
parentInfo[i] = new ParentInfo (st.nextToken().trim());
|
||||
} else {
|
||||
parent = null;
|
||||
parentInfo = null;
|
||||
}
|
||||
|
||||
lastTypeChange = props.lastModified ();
|
||||
|
@ -197,8 +198,8 @@ public final class DbMapping implements Updatable {
|
|||
parentMapping = app.getDbMapping (extendsProto);
|
||||
}
|
||||
|
||||
// if (table != null && source != null) {
|
||||
// app.logEvent ("set data source for "+typename+" to "+source);
|
||||
// if (tableName != null && dbSource != null) {
|
||||
// app.logEvent ("set data dbSource for "+typename+" to "+dbSource);
|
||||
HashMap p2d = new HashMap ();
|
||||
HashMap d2p = new HashMap ();
|
||||
|
||||
|
@ -210,10 +211,13 @@ public final class DbMapping implements Updatable {
|
|||
if (!propName.startsWith ("_") && propName.indexOf (".") < 0) {
|
||||
String dbField = props.getProperty (propName);
|
||||
// check if a relation for this propery already exists. If so, reuse it
|
||||
Relation rel = propertyToRelation (propName);
|
||||
Relation rel = (Relation) prop2db.get (propName.toLowerCase());
|
||||
if (rel == null)
|
||||
rel = new Relation (dbField, propName, this, props);
|
||||
rel.update (dbField, props);
|
||||
// key enumerations from SystemProperties are all lower case, which is why
|
||||
// even though we don't do a toLowerCase() here,
|
||||
// we have to when we lookup things in p2d later.
|
||||
p2d.put (propName, rel);
|
||||
if (rel.columnName != null &&
|
||||
(rel.reftype == Relation.PRIMITIVE ||
|
||||
|
@ -238,7 +242,7 @@ public final class DbMapping implements Updatable {
|
|||
subRelation.update (subnodeMapping, props);
|
||||
// if subnodes are accessed via access name or group name,
|
||||
// the subnode relation is also the property relation.
|
||||
if (subRelation.accessor != null || subRelation.groupby != null)
|
||||
if (subRelation.accessName != null || subRelation.groupby != null)
|
||||
propRelation = subRelation;
|
||||
} catch (Exception x) {
|
||||
app.logEvent ("Error reading _subnodes relation for "+typename+": "+x.getMessage ());
|
||||
|
@ -266,18 +270,23 @@ public final class DbMapping implements Updatable {
|
|||
* Get a JDBC connection for this DbMapping.
|
||||
*/
|
||||
public Connection getConnection () throws ClassNotFoundException, SQLException {
|
||||
// if source was previously not available, check again
|
||||
if (source == null && sourceName != null)
|
||||
source = app.getDbSource (sourceName);
|
||||
if (sourceName == null && parentMapping != null)
|
||||
return parentMapping.getConnection ();
|
||||
if (source == null) {
|
||||
if (sourceName == null)
|
||||
throw new SQLException ("Tried to get Connection from non-relational embedded data source.");
|
||||
if (dbSourceName == null) {
|
||||
if (parentMapping != null)
|
||||
return parentMapping.getConnection ();
|
||||
else
|
||||
throw new SQLException ("Datasource is not defined: "+sourceName+".");
|
||||
throw new SQLException ("Tried to get Connection from non-relational embedded data source.");
|
||||
}
|
||||
return source.getConnection ();
|
||||
if (tableName == null) {
|
||||
throw new SQLException ("Invalid DbMapping, _table not specified: "+this);
|
||||
}
|
||||
// if dbSource was previously not available, check again
|
||||
if (dbSource == null) {
|
||||
dbSource = app.getDbSource (dbSourceName);
|
||||
}
|
||||
if (dbSource == null) {
|
||||
throw new SQLException ("Datasource is not defined: "+dbSourceName+".");
|
||||
}
|
||||
return dbSource.getConnection ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -285,27 +294,23 @@ public final class DbMapping implements Updatable {
|
|||
* data source including URL, JDBC driver, username and password.
|
||||
*/
|
||||
public DbSource getDbSource () {
|
||||
if (source == null && parentMapping != null)
|
||||
return parentMapping.getDbSource ();
|
||||
return source;
|
||||
if (dbSource == null) {
|
||||
if (tableName != null && dbSourceName != null)
|
||||
dbSource = app.getDbSource (dbSourceName);
|
||||
else if (parentMapping != null)
|
||||
return parentMapping.getDbSource ();
|
||||
}
|
||||
return dbSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL of the data source used for this mapping.
|
||||
*/
|
||||
public String getSourceID () {
|
||||
if (source == null && parentMapping != null)
|
||||
return parentMapping.getSourceID ();
|
||||
return source == null ? "" : source.url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table name used for this type mapping.
|
||||
*/
|
||||
public String getTableName () {
|
||||
if (source == null && parentMapping != null)
|
||||
if (tableName == null && parentMapping != null)
|
||||
return parentMapping.getTableName ();
|
||||
return table;
|
||||
return tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -349,7 +354,7 @@ public final class DbMapping implements Updatable {
|
|||
* Get the column used for (internal) names of objects of this type.
|
||||
*/
|
||||
public String getNameField () {
|
||||
if (nameField == null && parentMapping != null)
|
||||
if (nameField == null && parentMapping != null)
|
||||
return parentMapping.getNameField ();
|
||||
return nameField;
|
||||
}
|
||||
|
@ -358,7 +363,7 @@ public final class DbMapping implements Updatable {
|
|||
* Get the column used for names of prototype.
|
||||
*/
|
||||
public String getPrototypeField () {
|
||||
if (protoField == null && parentMapping != null)
|
||||
if (protoField == null && parentMapping != null)
|
||||
return parentMapping.getPrototypeField ();
|
||||
return protoField;
|
||||
}
|
||||
|
@ -370,9 +375,13 @@ public final class DbMapping implements Updatable {
|
|||
public String columnNameToProperty (String columnName) {
|
||||
if (columnName == null)
|
||||
return null;
|
||||
if (table == null && parentMapping != null)
|
||||
return parentMapping.columnNameToProperty (columnName);
|
||||
Relation rel = (Relation) db2prop.get (columnName.toUpperCase ());
|
||||
return _columnNameToProperty (columnName.toUpperCase());
|
||||
}
|
||||
|
||||
private String _columnNameToProperty (final String columnName) {
|
||||
Relation rel = (Relation) db2prop.get (columnName);
|
||||
if (rel == null && parentMapping != null)
|
||||
return parentMapping._columnNameToProperty (columnName);
|
||||
if (rel != null && (rel.reftype == Relation.PRIMITIVE || rel.reftype == Relation.REFERENCE))
|
||||
return rel.propName;
|
||||
return null;
|
||||
|
@ -384,11 +393,15 @@ public final class DbMapping implements Updatable {
|
|||
public String propertyToColumnName (String propName) {
|
||||
if (propName == null)
|
||||
return null;
|
||||
if (table == null && parentMapping != null)
|
||||
return parentMapping.propertyToColumnName (propName);
|
||||
// FIXME: prop2db stores keys in lower case, because it gets them
|
||||
// from a SystemProperties object which converts keys to lower case.
|
||||
Relation rel = (Relation) prop2db.get (propName.toLowerCase());
|
||||
return _propertyToColumnName (propName.toLowerCase ());
|
||||
}
|
||||
|
||||
private String _propertyToColumnName (final String propName) {
|
||||
Relation rel = (Relation) prop2db.get (propName);
|
||||
if (rel == null && parentMapping != null)
|
||||
return parentMapping._propertyToColumnName (propName);
|
||||
if (rel != null && (rel.reftype == Relation.PRIMITIVE || rel.reftype == Relation.REFERENCE))
|
||||
return rel.columnName;
|
||||
return null;
|
||||
|
@ -400,9 +413,14 @@ public final class DbMapping implements Updatable {
|
|||
public Relation columnNameToRelation (String columnName) {
|
||||
if (columnName == null)
|
||||
return null;
|
||||
if (table == null && parentMapping != null)
|
||||
return parentMapping.columnNameToRelation (columnName);
|
||||
return (Relation) db2prop.get (columnName.toUpperCase ());
|
||||
return _columnNameToRelation (columnName.toUpperCase());
|
||||
}
|
||||
|
||||
private Relation _columnNameToRelation (final String columnName) {
|
||||
Relation rel = (Relation) db2prop.get (columnName);
|
||||
if (rel == null && parentMapping != null)
|
||||
return parentMapping._columnNameToRelation (columnName);
|
||||
return rel;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,11 +429,16 @@ public final class DbMapping implements Updatable {
|
|||
public Relation propertyToRelation (String propName) {
|
||||
if (propName == null)
|
||||
return null;
|
||||
if (table == null && parentMapping != null)
|
||||
return parentMapping.propertyToRelation (propName);
|
||||
// FIXME: prop2db stores keys in lower case, because it gets them
|
||||
// from a SystemProperties object which converts keys to lower case.
|
||||
return (Relation) prop2db.get (propName.toLowerCase());
|
||||
return _propertyToRelation (propName.toLowerCase());
|
||||
}
|
||||
|
||||
private Relation _propertyToRelation (String propName) {
|
||||
Relation rel = (Relation) prop2db.get (propName);
|
||||
if (rel == null && parentMapping != null)
|
||||
return parentMapping._propertyToRelation (propName);
|
||||
return rel;
|
||||
}
|
||||
|
||||
|
||||
|
@ -424,17 +447,17 @@ public final class DbMapping implements Updatable {
|
|||
* determine its parent object.
|
||||
*/
|
||||
public synchronized ParentInfo[] getParentInfo () {
|
||||
if (parent == null && parentMapping != null)
|
||||
return parentMapping.getParentInfo ();
|
||||
return parent;
|
||||
if (parentInfo == null && parentMapping != null)
|
||||
return parentMapping.getParentInfo ();
|
||||
return parentInfo;
|
||||
}
|
||||
|
||||
|
||||
public DbMapping getSubnodeMapping () {
|
||||
if (subRelation != null)
|
||||
return subRelation.otherType;
|
||||
if (parentMapping != null)
|
||||
return parentMapping.getSubnodeMapping ();
|
||||
if (parentMapping != null)
|
||||
return parentMapping.getSubnodeMapping ();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -551,7 +574,7 @@ public final class DbMapping implements Updatable {
|
|||
* not what we want.
|
||||
*/
|
||||
public boolean isRelational () {
|
||||
if (sourceName != null)
|
||||
if (dbSourceName != null)
|
||||
return true;
|
||||
if (parentMapping != null)
|
||||
return parentMapping.isRelational ();
|
||||
|
@ -565,7 +588,7 @@ public final class DbMapping implements Updatable {
|
|||
public synchronized DbColumn[] getColumns() throws ClassNotFoundException, SQLException {
|
||||
if (!isRelational ())
|
||||
throw new SQLException ("Can't get columns for non-relational data mapping "+this);
|
||||
if (source == null && parentMapping != null)
|
||||
if (dbSource == null && parentMapping != null)
|
||||
return parentMapping.getColumns ();
|
||||
// Use local variable cols to avoid synchronization (schema may be nulled elsewhere)
|
||||
if (columns == null) {
|
||||
|
@ -656,7 +679,7 @@ public final class DbMapping implements Updatable {
|
|||
* to be quoted in SQL queries.
|
||||
*/
|
||||
public boolean needsQuotes (String columnName) throws SQLException {
|
||||
if (table == null && parentMapping != null)
|
||||
if (tableName == null && parentMapping != null)
|
||||
return parentMapping.needsQuotes (columnName);
|
||||
try {
|
||||
DbColumn col = getColumn (columnName);
|
||||
|
@ -698,27 +721,38 @@ public final class DbMapping implements Updatable {
|
|||
|
||||
public void notifyDataChange () {
|
||||
lastDataChange = System.currentTimeMillis ();
|
||||
if (parentMapping != null && source == null)
|
||||
if (parentMapping != null && dbSource == null)
|
||||
parentMapping.notifyDataChange ();
|
||||
}
|
||||
|
||||
public synchronized long getNewID (long dbmax) {
|
||||
if (parentMapping != null && source == null)
|
||||
if (parentMapping != null && dbSource == null)
|
||||
return parentMapping.getNewID (dbmax);
|
||||
lastID = Math.max (dbmax+1, lastID+1);
|
||||
return lastID;
|
||||
}
|
||||
|
||||
public HashMap getProp2DB () {
|
||||
if (table == null && parentMapping != null)
|
||||
return parentMapping.getProp2DB ();
|
||||
return prop2db;
|
||||
|
||||
public Enumeration getPropertyEnumeration () {
|
||||
HashSet set = new HashSet ();
|
||||
collectPropertyNames (set);
|
||||
final Iterator it = set.iterator();
|
||||
return new Enumeration () {
|
||||
public boolean hasMoreElements() {
|
||||
return it.hasNext();
|
||||
}
|
||||
public Object nextElement() {
|
||||
return it.next();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Iterator getDBPropertyIterator () {
|
||||
if (table == null && parentMapping != null)
|
||||
return parentMapping.getDBPropertyIterator ();
|
||||
return db2prop.values ().iterator ();
|
||||
private void collectPropertyNames (HashSet basket) {
|
||||
// fetch propnames from parent mapping first, than add our own.
|
||||
if (parentMapping != null)
|
||||
parentMapping.collectPropertyNames (basket);
|
||||
if (!prop2db.isEmpty())
|
||||
basket.addAll (prop2db.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -727,9 +761,9 @@ public final class DbMapping implements Updatable {
|
|||
* db.
|
||||
*/
|
||||
public String getStorageTypeName () {
|
||||
if (table == null && parentMapping != null)
|
||||
if (tableName == null && parentMapping != null)
|
||||
return parentMapping.getStorageTypeName ();
|
||||
return sourceName == null ? null : typename;
|
||||
return dbSourceName == null ? null : typename;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -502,8 +502,8 @@ public final class Node implements INode, Serializable {
|
|||
Node p = parentHandle.getNode (nmgr);
|
||||
DbMapping parentmap = p.getDbMapping ();
|
||||
Relation prel = parentmap.getPropertyRelation();
|
||||
if (prel != null && prel.subnodesAreProperties && prel.accessor != null) {
|
||||
String propname = dbmap.columnNameToProperty (prel.accessor);
|
||||
if (prel != null && prel.hasAccessName()) {
|
||||
String propname = dbmap.columnNameToProperty (prel.accessName);
|
||||
String propvalue = getString (propname);
|
||||
if (propvalue != null && propvalue.length() > 0) {
|
||||
setName (propvalue);
|
||||
|
@ -664,9 +664,9 @@ public final class Node implements INode, Serializable {
|
|||
if (parentmap != null) {
|
||||
// first try to retrieve name via generic property relation of parent
|
||||
Relation prel = parentmap.getPropertyRelation ();
|
||||
if (prel != null && prel.otherType == dbmap && prel.accessor != null) {
|
||||
if (prel != null && prel.otherType == dbmap && prel.accessName != null) {
|
||||
// reverse look up property used to access this via parent
|
||||
Relation proprel = dbmap.columnNameToRelation (prel.accessor);
|
||||
Relation proprel = dbmap.columnNameToRelation (prel.accessName);
|
||||
if (proprel != null && proprel.propName != null)
|
||||
newname = getString (proprel.propName);
|
||||
}
|
||||
|
@ -773,17 +773,18 @@ public final class Node implements INode, Serializable {
|
|||
checkWriteLock ();
|
||||
node.checkWriteLock ();
|
||||
}
|
||||
|
||||
|
||||
// if subnodes are defined via realation, make sure its constraints are enforced.
|
||||
if (dbmap != null && dbmap.getSubnodeRelation () != null)
|
||||
if (dbmap != null && dbmap.getSubnodeRelation () != null) {
|
||||
dbmap.getSubnodeRelation ().setConstraints (this, node);
|
||||
|
||||
}
|
||||
|
||||
// if the new node is marked as TRANSIENT and this node is not, mark new node as NEW
|
||||
if (state != TRANSIENT && node.state == TRANSIENT)
|
||||
node.makePersistentCapable ();
|
||||
|
||||
String n = node.getName();
|
||||
|
||||
|
||||
// if (n.indexOf('/') > -1)
|
||||
// throw new RuntimeException ("\"/\" found in Node name.");
|
||||
|
||||
|
@ -809,7 +810,7 @@ public final class Node implements INode, Serializable {
|
|||
if (groupbyNode == null)
|
||||
groupbyNode = getGroupbySubnode (groupbyValue, true);
|
||||
groupbyNode.addNode (node);
|
||||
|
||||
|
||||
return node;
|
||||
} catch (Exception x) {
|
||||
System.err.println ("Error adding groupby: "+x);
|
||||
|
@ -836,10 +837,10 @@ public final class Node implements INode, Serializable {
|
|||
// check if properties are subnodes (_properties.aresubnodes=true)
|
||||
if (dbmap != null && node.dbmap != null) {
|
||||
Relation prel = dbmap.getPropertyRelation();
|
||||
if (prel != null && prel.accessor != null) {
|
||||
Relation localrel = node.dbmap.columnNameToRelation (prel.accessor);
|
||||
if (prel != null && prel.accessName != null) {
|
||||
Relation localrel = node.dbmap.columnNameToRelation (prel.accessName);
|
||||
// if no relation from db column to prop name is found, assume that both are equal
|
||||
String propname = localrel == null ? prel.accessor : localrel.propName;
|
||||
String propname = localrel == null ? prel.accessName : localrel.propName;
|
||||
String prop = node.getString (propname);
|
||||
if (prop != null && prop.length() > 0) {
|
||||
INode old = getNode (prop);
|
||||
|
@ -932,7 +933,7 @@ public final class Node implements INode, Serializable {
|
|||
if (rel != null)
|
||||
return (IPathElement) getNode (name);
|
||||
rel = dbmap.getSubnodeRelation ();
|
||||
if (rel != null && rel.groupby == null && rel.accessor != null) {
|
||||
if (rel != null && rel.groupby == null && rel.accessName != null) {
|
||||
if (rel.otherType != null && rel.otherType.isRelational ())
|
||||
return (IPathElement) nmgr.getNode (this, name, rel);
|
||||
else
|
||||
|
@ -1112,10 +1113,10 @@ public final class Node implements INode, Serializable {
|
|||
// check if subnodes are also accessed as properties. If so, also unset the property
|
||||
if (dbmap != null && node.dbmap != null) {
|
||||
Relation prel = dbmap.getPropertyRelation();
|
||||
if (prel != null && prel.accessor != null) {
|
||||
Relation localrel = node.dbmap.columnNameToRelation (prel.accessor);
|
||||
if (prel != null && prel.accessName != null) {
|
||||
Relation localrel = node.dbmap.columnNameToRelation (prel.accessName);
|
||||
// if no relation from db column to prop name is found, assume that both are equal
|
||||
String propname = localrel == null ? prel.accessor : localrel.propName;
|
||||
String propname = localrel == null ? prel.accessName : localrel.propName;
|
||||
String prop = node.getString (propname);
|
||||
if (prop != null && getNode (prop) == node)
|
||||
unset (prop);
|
||||
|
@ -1309,17 +1310,13 @@ public final class Node implements INode, Serializable {
|
|||
*/
|
||||
public Enumeration properties () {
|
||||
|
||||
if (dbmap != null && dbmap.isRelational() && dbmap.getProp2DB ().size() > 0)
|
||||
if (dbmap != null && dbmap.isRelational())
|
||||
// return the properties defined in type.properties, if there are any
|
||||
return new Enumeration () {
|
||||
Iterator i = dbmap.getProp2DB().keySet().iterator();
|
||||
public boolean hasMoreElements() {return i.hasNext();}
|
||||
public Object nextElement () {return i.next();}
|
||||
};
|
||||
return dbmap.getPropertyEnumeration();
|
||||
|
||||
Relation prel = dbmap == null ? null : dbmap.getPropertyRelation ();
|
||||
if (prel != null && prel.accessor != null && !prel.subnodesAreProperties
|
||||
&& prel.otherType != null && prel.otherType.isRelational ())
|
||||
if (prel != null && prel.hasAccessName()
|
||||
&& prel.otherType != null && prel.otherType.isRelational ())
|
||||
// return names of objects from a relational db table
|
||||
return nmgr.getPropertyNames (this, prel).elements ();
|
||||
else if (propMap != null)
|
||||
|
@ -1493,7 +1490,7 @@ public final class Node implements INode, Serializable {
|
|||
propMap.put (p2, prop);
|
||||
}
|
||||
|
||||
// check if this may have an effect on the node's URL when using subnodesAreProperties
|
||||
// check if this may have an effect on the node's URL when using accessname
|
||||
// but only do this if we already have a parent set, i.e. if we are already stored in the db
|
||||
Node parent = parentHandle == null ? null : (Node) getParent ();
|
||||
|
||||
|
@ -1504,7 +1501,7 @@ public final class Node implements INode, Serializable {
|
|||
Relation propRel = parentmap.getPropertyRelation ();
|
||||
String dbcolumn = dbmap.propertyToColumnName (propname);
|
||||
|
||||
if (propRel != null && propRel.accessor != null && propRel.accessor.equals (dbcolumn)) {
|
||||
if (propRel != null && propRel.accessName != null && propRel.accessName.equals (dbcolumn)) {
|
||||
INode n = parent.getNode (value);
|
||||
if (n != null && n != this) {
|
||||
parent.unset (value);
|
||||
|
@ -1748,7 +1745,7 @@ public final class Node implements INode, Serializable {
|
|||
// UPDATE: using n.getKey() instead of manually constructing key. HW 2002/09/13
|
||||
tx.visitCleanNode (n.getKey(), n);
|
||||
// if the field is not the primary key of the property, also register it
|
||||
if (rel != null && rel.accessor != null && state != TRANSIENT) {
|
||||
if (rel != null && rel.accessName != null && state != TRANSIENT) {
|
||||
Key secKey = new SyntheticKey (getKey (), propname);
|
||||
nmgr.evictKey (secKey);
|
||||
tx.visitCleanNode (secKey, n);
|
||||
|
|
|
@ -1027,8 +1027,8 @@ public final class NodeManager {
|
|||
}
|
||||
|
||||
String accessProp = null;
|
||||
if (rel.accessor != null && !rel.usesPrimaryKey ())
|
||||
accessProp = dbm.columnNameToProperty (rel.accessor);
|
||||
if (rel.accessName != null && !rel.usesPrimaryKey ())
|
||||
accessProp = dbm.columnNameToProperty (rel.accessName);
|
||||
|
||||
while (rs.next ()) {
|
||||
// create new Nodes.
|
||||
|
@ -1048,7 +1048,7 @@ public final class NodeManager {
|
|||
sn.add (new NodeHandle (primKey));
|
||||
}
|
||||
|
||||
// if relation doesn't use primary key as accessor, get accessor value
|
||||
// if relation doesn't use primary key as accessName, get accessName value
|
||||
String accessName = null;
|
||||
if (accessProp != null) {
|
||||
accessName = node.getString (accessProp);
|
||||
|
@ -1166,7 +1166,7 @@ public final class NodeManager {
|
|||
Vector retval = new Vector ();
|
||||
// if we do a groupby query (creating an intermediate layer of groupby nodes),
|
||||
// retrieve the value of that field instead of the primary key
|
||||
String namefield = rel.accessor;
|
||||
String namefield = rel.accessName;
|
||||
Connection con = rel.otherType.getConnection ();
|
||||
String table = rel.otherType.getTableName ();
|
||||
|
||||
|
@ -1267,12 +1267,9 @@ public final class NodeManager {
|
|||
node = (Node) home.createNode (kstr);
|
||||
else
|
||||
node = new Node (home, kstr, safe, rel.prototype);
|
||||
if (rel.prototype != null) {
|
||||
node.setPrototype (rel.prototype);
|
||||
node.setDbMapping (app.getDbMapping (rel.prototype));
|
||||
} else {
|
||||
node.setDbMapping (rel.getVirtualMapping ());
|
||||
}
|
||||
// set prototype and dbmapping on the newly created virtual/collection node
|
||||
node.setPrototype (rel.prototype);
|
||||
node.setDbMapping (rel.getVirtualMapping ());
|
||||
|
||||
} else if (rel != null && rel.groupby != null) {
|
||||
node = home.getGroupbySubnode (kstr, false);
|
||||
|
@ -1299,7 +1296,7 @@ public final class NodeManager {
|
|||
if (home.getSubnodeRelation () != null) {
|
||||
// combine our key with the constraints in the manually set subnode relation
|
||||
q.append ("WHERE ");
|
||||
q.append (rel.accessor);
|
||||
q.append (rel.accessName);
|
||||
q.append (" = '");
|
||||
q.append (escape(kstr));
|
||||
q.append ("'");
|
||||
|
|
|
@ -238,7 +238,7 @@ public final class Property implements IProperty, Serializable, Cloneable {
|
|||
// check if the property node is also a subnode
|
||||
// BUG: this doesn't work because properties for subnode/properties are never stored and therefore
|
||||
// never reused.
|
||||
if (nvrel != null && nvrel.subnodesAreProperties) {
|
||||
if (nvrel != null && nvrel.hasAccessName()) {
|
||||
node.removeNode (nvalue);
|
||||
}
|
||||
// only need to call unregisterPropLink if the value node is not stored in a relational db
|
||||
|
|
|
@ -52,10 +52,9 @@ public final class Relation {
|
|||
boolean readonly;
|
||||
boolean aggressiveLoading;
|
||||
boolean aggressiveCaching;
|
||||
boolean subnodesAreProperties;
|
||||
boolean isPrivate;
|
||||
|
||||
String accessor; // db column used to access objects through this relation
|
||||
String accessName; // db column used to access objects through this relation
|
||||
String order;
|
||||
String groupbyOrder;
|
||||
String groupby;
|
||||
|
@ -76,9 +75,8 @@ public final class Relation {
|
|||
this.columnName = rel.columnName;
|
||||
this.reftype = rel.reftype;
|
||||
this.constraints = rel.constraints;
|
||||
this.accessor = rel.accessor;
|
||||
this.accessName = rel.accessName;
|
||||
this.maxSize = rel.maxSize;
|
||||
this.subnodesAreProperties = rel.subnodesAreProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,10 +197,8 @@ public final class Relation {
|
|||
aggressiveLoading = aggressiveCaching = false;
|
||||
}
|
||||
// check if subnode condition should be applied for property relations
|
||||
accessor = props.getProperty (propName+".accessname");
|
||||
if (accessor != null)
|
||||
subnodesAreProperties = true;
|
||||
// parse contstraints
|
||||
accessName = props.getProperty (propName+".accessname");
|
||||
// parse contstraints
|
||||
String local = props.getProperty (propName+".local");
|
||||
String foreign = props.getProperty (propName+".foreign");
|
||||
if (local != null && foreign != null) {
|
||||
|
@ -257,7 +253,7 @@ public final class Relation {
|
|||
* and never stored to a persistent storage.
|
||||
*/
|
||||
public boolean createPropertyOnDemand () {
|
||||
return virtual || accessor != null || groupby != null;
|
||||
return virtual || accessName != null || groupby != null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -321,13 +317,17 @@ public final class Relation {
|
|||
if (reftype == REFERENCE)
|
||||
return constraints.length == 1 && constraints[0].foreignKeyIsPrimary ();
|
||||
if (reftype == COLLECTION)
|
||||
return accessor == null || accessor.equalsIgnoreCase (otherType.getIDField ());
|
||||
return accessName == null || accessName.equalsIgnoreCase (otherType.getIDField ());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getAccessor () {
|
||||
return accessor;
|
||||
public boolean hasAccessName () {
|
||||
return accessName != null;
|
||||
}
|
||||
|
||||
public String getAccessName () {
|
||||
return accessName;
|
||||
}
|
||||
|
||||
public Relation getSubnodeRelation () {
|
||||
|
@ -344,9 +344,20 @@ public final class Relation {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* get a DbMapping to use for virtual aka collection nodes.
|
||||
*/
|
||||
public DbMapping getVirtualMapping () {
|
||||
// return null unless this relation describes a virtual/collection node.
|
||||
if (!virtual)
|
||||
return null;
|
||||
// if the collection node is prototyped, return the app's DbMapping
|
||||
// for that prototype
|
||||
if (prototype != null) {
|
||||
return otherType;
|
||||
}
|
||||
// create a synthetic DbMapping that describes how to fetch the
|
||||
// collection's child objects.
|
||||
if (virtualMapping == null) {
|
||||
virtualMapping = new DbMapping (ownType.app);
|
||||
virtualMapping.subRelation = getVirtualSubnodeRelation ();
|
||||
|
@ -434,7 +445,7 @@ public final class Relation {
|
|||
String prefix = pre;
|
||||
if (kstr != null) {
|
||||
q.append (prefix);
|
||||
String accessColumn = accessor == null ? otherType.getIDField () : accessor;
|
||||
String accessColumn = accessName == null ? otherType.getIDField () : accessName;
|
||||
q.append (accessColumn);
|
||||
q.append (" = ");
|
||||
// check if column is string type and value needs to be quoted
|
||||
|
|
|
@ -8,6 +8,7 @@ import helma.framework.core.*;
|
|||
import helma.objectmodel.*;
|
||||
import helma.util.*;
|
||||
import helma.framework.IPathElement;
|
||||
import helma.scripting.ScriptingException;
|
||||
import FESI.Interpreter.*;
|
||||
import FESI.Exceptions.*;
|
||||
import FESI.Extensions.*;
|
||||
|
@ -759,10 +760,29 @@ public final class HopExtension {
|
|||
Object elem = thisObject.toJavaObject ();
|
||||
String tmpname = arguments.length == 0 ? "" : arguments[0].toString ();
|
||||
String basicHref =app.getNodeHref (elem, tmpname);
|
||||
// check if the app.properties specify a href-function to post-process the
|
||||
// basic href.
|
||||
String hrefFunction = app.getProperty ("hrefFunction", null);
|
||||
if (hrefFunction != null) {
|
||||
Object funcElem = elem;
|
||||
while (funcElem != null) {
|
||||
if (engine.hasFunction (funcElem, hrefFunction)) {
|
||||
Object obj;
|
||||
try {
|
||||
obj = engine.invoke (funcElem, hrefFunction, new Object[] {basicHref}, false);
|
||||
} catch (ScriptingException x) {
|
||||
throw new RuntimeException ("Error in hrefFunction: "+x);
|
||||
}
|
||||
if (obj == null)
|
||||
throw new RuntimeException ("hrefFunction "+hrefFunction+" returned null");
|
||||
basicHref = obj.toString ();
|
||||
}
|
||||
funcElem = app.getParentElement (funcElem);
|
||||
}
|
||||
}
|
||||
// check if the app.properties specify a href-skin to post-process the
|
||||
// basic href.
|
||||
String hrefSkin = app.getProperty ("hrefSkin", null);
|
||||
|
||||
// FIXME: we should actually walk down the path from the object we called href() on
|
||||
// instead we move down the URL path.
|
||||
if (hrefSkin != null) {
|
||||
// we need to post-process the href with a skin for this application
|
||||
// first, look in the object href was called on.
|
||||
|
@ -774,29 +794,24 @@ public final class HopExtension {
|
|||
Prototype proto = app.getPrototype (skinElem);
|
||||
if (proto != null) {
|
||||
skin = proto.getSkin (hrefSkin);
|
||||
/* String skinid = proto.getName()+"/"+hrefSkin;
|
||||
skin = res.getCachedSkin (skinid);
|
||||
if (skin == null) {
|
||||
skin = app.getSkin (skinElem, hrefSkin, skinpath);
|
||||
res.cacheSkin (skinid, skin);
|
||||
} */
|
||||
}
|
||||
if (skin == null)
|
||||
skinElem = app.getParentElement (skinElem);
|
||||
}
|
||||
|
||||
if (skin != null) {
|
||||
return renderSkin (skin, basicHref, skinElem);
|
||||
basicHref = renderSkin (skin, basicHref, skinElem);
|
||||
}
|
||||
}
|
||||
|
||||
return new ESString (basicHref);
|
||||
}
|
||||
private ESString renderSkin (Skin skin, String path, Object skinElem) throws EcmaScriptException {
|
||||
private String renderSkin (Skin skin, String path, Object skinElem) throws EcmaScriptException {
|
||||
engine.getResponse().pushStringBuffer ();
|
||||
HashMap param = new HashMap ();
|
||||
param.put ("path", path);
|
||||
skin.render (engine.getRequestEvaluator(), skinElem, param);
|
||||
return new ESString (engine.getResponse().popStringBuffer ().trim ());
|
||||
return engine.getResponse().popStringBuffer ().trim ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -241,13 +241,11 @@ public abstract class AbstractServletClient extends HttpServlet {
|
|||
|
||||
if (!hopres.cache || ! caching) {
|
||||
// Disable caching of response.
|
||||
if (isOneDotOne (req.getProtocol ())) {
|
||||
// for HTTP 1.0
|
||||
res.setHeader ("Pragma", "no-cache");
|
||||
} else {
|
||||
// for HTTP 1.1
|
||||
res.setHeader ("Cache-Control", "no-cache");
|
||||
}
|
||||
// for HTTP 1.0
|
||||
res.setDateHeader ("Expires", System.currentTimeMillis ()-10000);
|
||||
res.setHeader ("Pragma", "no-cache");
|
||||
// for HTTP 1.1
|
||||
res.setHeader ("Cache-Control", "no-cache, no-store, must-revalidate, max-age=0");
|
||||
}
|
||||
if ( hopres.realm!=null )
|
||||
res.setHeader( "WWW-Authenticate", "Basic realm=\"" + hopres.realm + "\"" );
|
||||
|
|
675
src/helma/util/CronJob.java
Normal file
675
src/helma/util/CronJob.java
Normal file
|
@ -0,0 +1,675 @@
|
|||
package helma.util;
|
||||
|
||||
/**
|
||||
* Modifications by Stefan Pollach, 2002-08, 2003-03
|
||||
* First, to compile without protomatter-library (we're only interested in the
|
||||
* parsing functions for helma), second to encapsulate a function call and not
|
||||
* a PASEvent
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Protomatter Software License, Version 1.0
|
||||
* derived from The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 1998-2002 Nate Sammons. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed for the
|
||||
* Protomatter Software Project
|
||||
* (http://protomatter.sourceforge.net/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Protomatter" and "Protomatter Software Project" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact support@protomatter.com.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Protomatter",
|
||||
* nor may "Protomatter" appear in their name, without prior written
|
||||
* permission of the Protomatter Software Project
|
||||
* (support@protomatter.com).
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE PROTOMATTER SOFTWARE PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* A cron entry, derived from Protomatter's CronEntry class.
|
||||
* This class encapsulates a function call, a timeout value
|
||||
* and a specification for when the given event should be
|
||||
* delivered to the given topics. The specification of when
|
||||
* the event should be delivered is based on the UNIX cron
|
||||
* facility.
|
||||
*/
|
||||
|
||||
|
||||
public class CronJob {
|
||||
|
||||
// used as the value in hashtables
|
||||
private static Object value = new Object();
|
||||
private static Hashtable all = new Hashtable ();
|
||||
private static String ALL_VALUE = "*";
|
||||
|
||||
private Hashtable year;
|
||||
private Hashtable month;
|
||||
private Hashtable day;
|
||||
private Hashtable weekday;
|
||||
private Hashtable hour;
|
||||
private Hashtable minute;
|
||||
|
||||
private String name = null;
|
||||
private String function = null;
|
||||
private long timeout = 30000;
|
||||
|
||||
/** A method for parsing properties. It looks through the properties
|
||||
* file for entries that look like this:
|
||||
*
|
||||
* <blockquote><pre>
|
||||
* cron.name1.function = functionname
|
||||
*
|
||||
* cron.name1.year = year-list
|
||||
* cron.name1.month = month-list
|
||||
* cron.name1.day = day-list
|
||||
* cron.name1.weekday = weekday-list
|
||||
* cron.name1.hour = hour-list
|
||||
* cron.name1.minute = minute-list
|
||||
*
|
||||
* cron.name1.timeout = timeout-value
|
||||
*
|
||||
* </pre></blockquote><p>
|
||||
*
|
||||
* And delivers corresponding <tt>CronJob</tt> objects in a collection.
|
||||
* The specified lists from above are:<P>
|
||||
*
|
||||
* <ul><dl>
|
||||
* <dt><tt>year-list</tt></dt>
|
||||
** <dd>
|
||||
** This is a comma (<tt>,</tt>) separated list of individual
|
||||
* years or of year ranges. Examples: "<tt>1999,2000</tt>" or
|
||||
* "<tt>1999-2004,2005-2143,2650</tt>"
|
||||
* </dd><P>
|
||||
*
|
||||
* <dt><tt>month-list</tt></dt>
|
||||
* <dd>
|
||||
* This is a comma (<tt>,</tt>) separated list of month
|
||||
* names. Example: "<tt>january,march,may</tt>"
|
||||
* </dd><P>
|
||||
*
|
||||
* <dt><tt>day-list</tt></dt>
|
||||
* <dd>
|
||||
* This is a comma (<tt>,</tt>) separated list of individual
|
||||
* day-of-month numbers or of day-of-month ranges.
|
||||
* Examples: "<tt>1,15</tt>" or "<tt>1-5,7,10-24</tt>"
|
||||
* </dd><P>
|
||||
*
|
||||
* <dt><tt>weekday-list</tt></dt>
|
||||
* <dd>
|
||||
* This is a comma (<tt>,</tt>) separated list of weekday names
|
||||
* names. Example: "<tt>monday,tuesday</tt>"
|
||||
* </dd><P>
|
||||
*
|
||||
* <dt><tt>hour-list</tt></dt>
|
||||
* <dd>
|
||||
* This is a comma (<tt>,</tt>) separated list of individual
|
||||
* hours-of-day (24-hour time) or of hour-of-day ranges.
|
||||
* Examples: "<tt>12,15</tt>" or "<tt>8-17,19,20-22</tt>"
|
||||
* </dd><P>
|
||||
*
|
||||
* <dt><tt>minute-list</tt></dt>
|
||||
* <dd>
|
||||
* This is a comma (<tt>,</tt>) separated list of individual
|
||||
* minutes (during an hour) or of minute ranges.
|
||||
* Examples: "<tt>0,15,30,45</tt>" or "<tt>0-5,8-14,23,28-32</tt>"
|
||||
* </dd><P>
|
||||
*
|
||||
* </dl></ul>
|
||||
*
|
||||
* The value of each of those lists can also be an asterisk (<tt>*</tt>),
|
||||
* which tells the cron system to disregard the given list when
|
||||
* determining if a cron entry applies to a specific time -- for instance
|
||||
* setting the <tt>year-list</tt> to <tt>*</tt> would cause the system to
|
||||
* not take the current year into consideration. If a given list is
|
||||
* not specified at all, it's the same as specifying it and giving it
|
||||
* a value of <tt>*</tt>.<P>
|
||||
*/
|
||||
|
||||
|
||||
public static Collection parse(Properties props) {
|
||||
Hashtable jobs = new Hashtable ();
|
||||
Enumeration e = props.keys ();
|
||||
while (e.hasMoreElements ()) {
|
||||
String key = (String) e.nextElement ();
|
||||
if (!key.startsWith ("cron."))
|
||||
continue;
|
||||
try {
|
||||
StringTokenizer st = new StringTokenizer (key.trim(), ".");
|
||||
st.nextElement ();
|
||||
String jobName = st.nextToken ();
|
||||
String jobSpec = st.nextToken ();
|
||||
if (jobSpec==null || jobSpec.equals("")) // might happen with cron.testname. = XXX
|
||||
continue;
|
||||
CronJob job = (CronJob) jobs.get (jobName);
|
||||
if (job==null) {
|
||||
job = new CronJob (jobName);
|
||||
jobs.put (jobName, job);
|
||||
}
|
||||
String value = props.getProperty (key);
|
||||
if (jobSpec.equalsIgnoreCase("function")) {
|
||||
job.setFunction(value);
|
||||
} else if (jobSpec.equalsIgnoreCase("year")) {
|
||||
parseYear (job, value);
|
||||
} else if (jobSpec.equalsIgnoreCase("month")) {
|
||||
parseMonth (job, value);
|
||||
} else if (jobSpec.equalsIgnoreCase("day")) {
|
||||
parseDay (job, value);
|
||||
} else if (jobSpec.equalsIgnoreCase("weekday")) {
|
||||
parseWeekDay (job, value);
|
||||
} else if (jobSpec.equalsIgnoreCase("hour")) {
|
||||
parseHour (job, value);
|
||||
} else if (jobSpec.equalsIgnoreCase("minute")) {
|
||||
parseMinute (job, value);
|
||||
}
|
||||
} catch (NoSuchElementException nsee) {
|
||||
}
|
||||
}
|
||||
return jobs.values ();
|
||||
}
|
||||
|
||||
|
||||
public static void parseYear (CronJob job, String value) {
|
||||
if (value.equals("*")) {
|
||||
job.setAllYears(true);
|
||||
} else {
|
||||
StringTokenizer st = new StringTokenizer(value.trim(), ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
String s = st.nextToken();
|
||||
if (s.indexOf("-") != -1) {
|
||||
int start = Integer.parseInt(s.substring(0, s.indexOf("-")));
|
||||
int finish = Integer.parseInt(s.substring(s.indexOf("-") +1));
|
||||
for (int i=start; i<=finish; i++) {
|
||||
job.addYear(i);
|
||||
}
|
||||
} else {
|
||||
int y = Integer.parseInt(s);
|
||||
job.addYear(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void parseMonth (CronJob job, String value) {
|
||||
if (value.equals("*")) {
|
||||
job.setAllMonths(true);
|
||||
} else {
|
||||
StringTokenizer st = new StringTokenizer(value.trim(), ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
String m = st.nextToken();
|
||||
if (m.equalsIgnoreCase("january"))
|
||||
job.addMonth(Calendar.JANUARY);
|
||||
if (m.equalsIgnoreCase("february"))
|
||||
job.addMonth(Calendar.FEBRUARY);
|
||||
if (m.equalsIgnoreCase("march"))
|
||||
job.addMonth(Calendar.MARCH);
|
||||
if (m.equalsIgnoreCase("april"))
|
||||
job.addMonth(Calendar.APRIL);
|
||||
if (m.equalsIgnoreCase("may"))
|
||||
job.addMonth(Calendar.MAY);
|
||||
if (m.equalsIgnoreCase("june"))
|
||||
job.addMonth(Calendar.JUNE);
|
||||
if (m.equalsIgnoreCase("july"))
|
||||
job.addMonth(Calendar.JULY);
|
||||
if (m.equalsIgnoreCase("august"))
|
||||
job.addMonth(Calendar.AUGUST);
|
||||
if (m.equalsIgnoreCase("september"))
|
||||
job.addMonth(Calendar.SEPTEMBER);
|
||||
if (m.equalsIgnoreCase("october"))
|
||||
job.addMonth(Calendar.OCTOBER);
|
||||
if (m.equalsIgnoreCase("november"))
|
||||
job.addMonth(Calendar.NOVEMBER);
|
||||
if (m.equalsIgnoreCase("december"))
|
||||
job.addMonth(Calendar.DECEMBER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void parseDay (CronJob job, String day) {
|
||||
if (day.equals("*")) {
|
||||
job.setAllDays(true);
|
||||
} else {
|
||||
StringTokenizer st = new StringTokenizer(day.trim(), ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
String s = st.nextToken();
|
||||
if (s.indexOf("-") != -1) {
|
||||
int start = Integer.parseInt(s.substring(0, s.indexOf("-")));
|
||||
int finish = Integer.parseInt(s.substring(s.indexOf("-") +1));
|
||||
for (int i=start; i<=finish; i++) {
|
||||
job.addDay(i);
|
||||
}
|
||||
} else {
|
||||
int d = Integer.parseInt(s);
|
||||
job.addDay(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void parseWeekDay (CronJob job, String weekday) {
|
||||
if (weekday.equals("*")) {
|
||||
job.setAllWeekdays(true);
|
||||
} else {
|
||||
StringTokenizer st = new StringTokenizer(weekday.trim(), ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
String d = st.nextToken();
|
||||
if (d.equalsIgnoreCase("monday"))
|
||||
job.addWeekday(Calendar.MONDAY);
|
||||
if (d.equalsIgnoreCase("tuesday"))
|
||||
job.addWeekday(Calendar.TUESDAY);
|
||||
if (d.equalsIgnoreCase("wednesday"))
|
||||
job.addWeekday(Calendar.WEDNESDAY);
|
||||
if (d.equalsIgnoreCase("thursday"))
|
||||
job.addWeekday(Calendar.THURSDAY);
|
||||
if (d.equalsIgnoreCase("friday"))
|
||||
job.addWeekday(Calendar.FRIDAY);
|
||||
if (d.equalsIgnoreCase("saturday"))
|
||||
job.addWeekday(Calendar.SATURDAY);
|
||||
if (d.equalsIgnoreCase("sunday"))
|
||||
job.addWeekday(Calendar.SUNDAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void parseHour (CronJob job, String hour) {
|
||||
if (hour.equals("*")) {
|
||||
job.setAllHours(true);
|
||||
} else {
|
||||
StringTokenizer st = new StringTokenizer(hour.trim (), ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
String s = st.nextToken();
|
||||
if (s.indexOf("-") != -1) {
|
||||
int start = Integer.parseInt(s.substring(0, s.indexOf("-")));
|
||||
int finish = Integer.parseInt(s.substring(s.indexOf("-") +1));
|
||||
for (int i=start; i<=finish; i++) {
|
||||
job.addHour(i);
|
||||
}
|
||||
} else {
|
||||
int h = Integer.parseInt(s);
|
||||
job.addHour(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void parseMinute (CronJob job, String minute) {
|
||||
if (minute.equals("*")) {
|
||||
job.setAllMinutes(true);
|
||||
} else {
|
||||
StringTokenizer st = new StringTokenizer(minute.trim (), ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
String s = st.nextToken();
|
||||
if (s.indexOf("-") != -1) {
|
||||
int start = Integer.parseInt(s.substring(0, s.indexOf("-")));
|
||||
int finish = Integer.parseInt(s.substring(s.indexOf("-") +1));
|
||||
for (int i=start; i<=finish; i++) {
|
||||
job.addMinute(i);
|
||||
}
|
||||
} else {
|
||||
int m = Integer.parseInt(s);
|
||||
job.addMinute(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create an empty CronJob.
|
||||
*/
|
||||
public CronJob (String name) {
|
||||
this.name = name;
|
||||
all.put (ALL_VALUE, value);
|
||||
year = new Hashtable (all);
|
||||
month = new Hashtable (all);
|
||||
day = new Hashtable (all);
|
||||
weekday = new Hashtable (all);
|
||||
hour = new Hashtable (all);
|
||||
minute = new Hashtable (all);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if this CronJob applies to the given date.
|
||||
* Seconds and milliseconds in the date are ignored.
|
||||
*/
|
||||
public boolean appliesToDate(Date date)
|
||||
{
|
||||
GregorianCalendar cal = new GregorianCalendar();
|
||||
cal.setTime(date);
|
||||
|
||||
// try and short-circuit as fast as possible.
|
||||
Integer theYear = new Integer(cal.get(Calendar.YEAR));
|
||||
if (!year.containsKey(ALL_VALUE) && !year.containsKey(theYear))
|
||||
return false;
|
||||
|
||||
Integer theMonth = new Integer(cal.get(Calendar.MONTH));
|
||||
if (!month.containsKey(ALL_VALUE) && !month.containsKey(theMonth))
|
||||
return false;
|
||||
|
||||
Integer theDay = new Integer(cal.get(Calendar.DAY_OF_MONTH));
|
||||
if (!day.containsKey(ALL_VALUE) && !day.containsKey(theDay))
|
||||
return false;
|
||||
|
||||
Integer theWeekDay = new Integer(cal.get(Calendar.DAY_OF_WEEK));
|
||||
if (!weekday.containsKey(ALL_VALUE) && !weekday.containsKey(theWeekDay))
|
||||
return false;
|
||||
|
||||
Integer theHour = new Integer(cal.get(Calendar.HOUR_OF_DAY));
|
||||
if (!hour.containsKey(ALL_VALUE) && !hour.containsKey(theHour))
|
||||
return false;
|
||||
|
||||
Integer theMinute = new Integer(cal.get(Calendar.MINUTE));
|
||||
if (!minute.containsKey(ALL_VALUE) && !minute.containsKey(theMinute))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a year to the list of years this entry applies to.
|
||||
*/
|
||||
public void addYear(int year)
|
||||
{
|
||||
this.year.remove(ALL_VALUE);
|
||||
this.year.put(new Integer(year), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a year from the list of years this entry applies to.
|
||||
*/
|
||||
public void removeYear(int year)
|
||||
{
|
||||
this.year.remove(new Integer(year));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the current year be taken into consideration when
|
||||
* deciding if this entry is applicable?
|
||||
* If this is set to false (the default) then the values set with
|
||||
* the <tt>addYear()</tt> and <tt>removeYear()</tt> are taken
|
||||
* into consideration. If this is set to true then the current
|
||||
* year is not taken into consideration.
|
||||
*/
|
||||
public void setAllYears(boolean set)
|
||||
{
|
||||
if (set)
|
||||
this.year.put(ALL_VALUE, value);
|
||||
else
|
||||
this.year.remove(ALL_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a month to the list of years this entry applies to.
|
||||
* Month numbers are taken from the constants on the
|
||||
* <tt>java.util.Calendar</tt> class.
|
||||
*/
|
||||
public void addMonth(int month)
|
||||
{
|
||||
this.month.remove(ALL_VALUE);
|
||||
this.month.put(new Integer(month), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a month from the list of years this entry applies to.
|
||||
* Month numbers are taken from the constants on the
|
||||
* <tt>java.util.Calendar</tt> class.
|
||||
*/
|
||||
public void removeMonth(int month)
|
||||
{
|
||||
this.month.remove(new Integer(month));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the current month be taken into consideration when
|
||||
* deciding if this entry is applicable?
|
||||
* If this is set to false (the default) then the values set with
|
||||
* the <tt>addMonth()</tt> and <tt>removeMonth()</tt> are taken
|
||||
* into consideration. If this is set to true then the current
|
||||
* month is not taken into consideration.
|
||||
*/
|
||||
public void setAllMonths(boolean set)
|
||||
{
|
||||
if (set)
|
||||
this.month.put(ALL_VALUE, value);
|
||||
else
|
||||
this.month.remove(ALL_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a day of the month to the list of years this entry applies to.
|
||||
*/
|
||||
public void addDay(int day)
|
||||
{
|
||||
this.day.remove(ALL_VALUE);
|
||||
this.day.put(new Integer(day), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a day of the month from the list of years this entry applies to.
|
||||
*/
|
||||
public void removeDay(int day)
|
||||
{
|
||||
this.day.remove(new Integer(day));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the current day of the month be taken into consideration when
|
||||
* deciding if this entry is applicable?
|
||||
* If this is set to false (the default) then the values set with
|
||||
* the <tt>addDay()</tt> and <tt>removeDay()</tt> are taken
|
||||
* into consideration. If this is set to true then the current
|
||||
* year is not taken into consideration.
|
||||
*/
|
||||
public void setAllDays(boolean set)
|
||||
{
|
||||
if (set)
|
||||
this.day.put(ALL_VALUE, value);
|
||||
else
|
||||
this.day.remove(ALL_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a weekday to the list of years this entry applies to.
|
||||
* Weekday numbers are taken from the constants on the
|
||||
* <tt>java.util.Calendar</tt> class.
|
||||
*/
|
||||
public void addWeekday(int weekday)
|
||||
{
|
||||
this.weekday.remove(ALL_VALUE);
|
||||
this.weekday.put(new Integer(weekday), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a weekday from the list of years this entry applies to.
|
||||
* Weekday numbers are taken from the constants on the
|
||||
* <tt>java.util.Calendar</tt> class.
|
||||
*/
|
||||
public void removeWeekday(int weekday)
|
||||
{
|
||||
this.weekday.remove(new Integer(weekday));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the current weekday be taken into consideration when
|
||||
* deciding if this entry is applicable?
|
||||
* If this is set to false (the default) then the values set with
|
||||
* the <tt>addWeekday()</tt> and <tt>removeWeekday()</tt> are taken
|
||||
* into consideration. If this is set to true then the current
|
||||
* weekday is not taken into consideration.
|
||||
*/
|
||||
public void setAllWeekdays(boolean set)
|
||||
{
|
||||
if (set)
|
||||
this.weekday.put(ALL_VALUE, value);
|
||||
else
|
||||
this.weekday.remove(ALL_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an hour to the list of years this entry applies to.
|
||||
*/
|
||||
public void addHour(int hour)
|
||||
{
|
||||
this.hour.remove(ALL_VALUE);
|
||||
this.hour.put(new Integer(hour), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an hour from the list of years this entry applies to.
|
||||
*/
|
||||
public void removeHour(int hour)
|
||||
{
|
||||
this.hour.remove(new Integer(hour));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the current hour be taken into consideration when
|
||||
* deciding if this entry is applicable?
|
||||
* If this is set to false (the default) then the values set with
|
||||
* the <tt>addHour()</tt> and <tt>removeHour()</tt> are taken
|
||||
* into consideration. If this is set to true then the current
|
||||
* hour is not taken into consideration.
|
||||
*/
|
||||
public void setAllHours(boolean set)
|
||||
{
|
||||
if (set)
|
||||
this.hour.put(ALL_VALUE, value);
|
||||
else
|
||||
this.hour.remove(ALL_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a minute to the list of years this entry applies to.
|
||||
*/
|
||||
public void addMinute(int minute)
|
||||
{
|
||||
this.minute.remove(ALL_VALUE);
|
||||
this.minute.put(new Integer(minute), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a minute from the list of years this entry applies to.
|
||||
*/
|
||||
public void removeMinute(int minute)
|
||||
{
|
||||
this.minute.remove(new Integer(minute));
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the current minute be taken into consideration when
|
||||
* deciding if this entry is applicable?
|
||||
* If this is set to false (the default) then the values set with
|
||||
* the <tt>addMinute()</tt> and <tt>removeMinute()</tt> are taken
|
||||
* into consideration. If this is set to true then the current
|
||||
* minute is not taken into consideration.
|
||||
*/
|
||||
public void setAllMinutes(boolean set)
|
||||
{
|
||||
if (set)
|
||||
this.minute.put(ALL_VALUE, value);
|
||||
else
|
||||
this.minute.remove(ALL_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set this entry's name
|
||||
*/
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this entry's name
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this entry's function
|
||||
*/
|
||||
public void setFunction(String function)
|
||||
{
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this entry's function
|
||||
*/
|
||||
public String getFunction()
|
||||
{
|
||||
return this.function;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set this entry's timeout
|
||||
*/
|
||||
public void setTimeout(long timeout)
|
||||
{
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this entry's timeout
|
||||
*/
|
||||
public void setTimeout(String timeout)
|
||||
{
|
||||
this.timeout = Long.valueOf(timeout).longValue ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this entry's timeout
|
||||
*/
|
||||
public long getTimeout()
|
||||
{
|
||||
return this.timeout;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue