Major clean-up work on Application constructors. Removed some old
options like setting application file extensions etc. Instead now the Application constructors can take arguments for the app and db home directories. Updated helma.main.ApplicationManager and helma.servlet.StandaloneServletClient to the new constructors. TypeManager now has file extensions as static final members.
This commit is contained in:
parent
c044ab86ab
commit
65b8d6b2c4
4 changed files with 121 additions and 87 deletions
|
@ -31,9 +31,14 @@ public final class Application
|
||||||
extends UnicastRemoteObject
|
extends UnicastRemoteObject
|
||||||
implements IRemoteApp, IPathElement, IReplicatedApp, Runnable {
|
implements IRemoteApp, IPathElement, IReplicatedApp, Runnable {
|
||||||
|
|
||||||
|
// the name of this application
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
// properties and db-properties
|
||||||
SystemProperties props, dbProps;
|
SystemProperties props, dbProps;
|
||||||
|
// home, app and data directories
|
||||||
File home, appDir, dbDir;
|
File home, appDir, dbDir;
|
||||||
|
// this application's node manager
|
||||||
protected NodeManager nmgr;
|
protected NodeManager nmgr;
|
||||||
|
|
||||||
// the root of the website, if a custom root object is defined.
|
// the root of the website, if a custom root object is defined.
|
||||||
|
@ -72,6 +77,7 @@ public final class Application
|
||||||
Hashtable dbMappings;
|
Hashtable dbMappings;
|
||||||
Hashtable dbSources;
|
Hashtable dbSources;
|
||||||
|
|
||||||
|
// internal worker thread for scheduler, session cleanup etc.
|
||||||
Thread worker;
|
Thread worker;
|
||||||
long requestTimeout = 60000; // 60 seconds for request timeout.
|
long requestTimeout = 60000; // 60 seconds for request timeout.
|
||||||
ThreadGroup threadgroup;
|
ThreadGroup threadgroup;
|
||||||
|
@ -82,10 +88,10 @@ public final class Application
|
||||||
// Two logs for each application: events and accesses
|
// Two logs for each application: events and accesses
|
||||||
Logger eventLog, accessLog;
|
Logger eventLog, accessLog;
|
||||||
|
|
||||||
protected String templateExtension, scriptExtension, actionExtension, skinExtension;
|
|
||||||
|
|
||||||
// A transient node that is shared among all evaluators
|
// A transient node that is shared among all evaluators
|
||||||
protected INode cachenode;
|
protected INode cachenode;
|
||||||
|
|
||||||
|
// some fields for statistics
|
||||||
protected volatile long requestCount = 0;
|
protected volatile long requestCount = 0;
|
||||||
protected volatile long xmlrpcCount = 0;
|
protected volatile long xmlrpcCount = 0;
|
||||||
protected volatile long errorCount = 0;
|
protected volatile long errorCount = 0;
|
||||||
|
@ -99,9 +105,7 @@ public final class Application
|
||||||
|
|
||||||
private DbMapping rootMapping, userRootMapping, userMapping;
|
private DbMapping rootMapping, userRootMapping, userMapping;
|
||||||
|
|
||||||
// boolean checkSubnodes;
|
// name of response encoding
|
||||||
|
|
||||||
// name of respone encoding
|
|
||||||
String charset;
|
String charset;
|
||||||
|
|
||||||
// password file to use for authenticate() function
|
// password file to use for authenticate() function
|
||||||
|
@ -118,62 +122,72 @@ public final class Application
|
||||||
/**
|
/**
|
||||||
* Zero argument constructor needed for RMI
|
* Zero argument constructor needed for RMI
|
||||||
*/
|
*/
|
||||||
public Application () throws RemoteException {
|
/* public Application () throws RemoteException {
|
||||||
super ();
|
super ();
|
||||||
}
|
} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an application with the given name in the home directory. Server-wide properties will
|
* Build an application with the given name in the app directory. No Server-wide
|
||||||
* be created if the files are present, but they don't have to.
|
* properties are created or used.
|
||||||
*/
|
*/
|
||||||
public Application (String name, File home) throws RemoteException, IllegalArgumentException {
|
public Application (String name, File appDir, File dbDir)
|
||||||
this (name, home,
|
throws RemoteException, IllegalArgumentException {
|
||||||
new SystemProperties (new File (home, "server.properties").getAbsolutePath ()),
|
this (name, null, appDir, dbDir);
|
||||||
new SystemProperties (new File (home, "db.properties").getAbsolutePath ()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an application with the given name, app and db properties and app base directory. The
|
* Build an application with the given name and server instance. The
|
||||||
* app directories will be created if they don't exist already.
|
* app directories will be created if they don't exist already.
|
||||||
*/
|
*/
|
||||||
public Application (String name, File home, SystemProperties sysProps, SystemProperties sysDbProps)
|
public Application (String name, Server server)
|
||||||
|
throws RemoteException, IllegalArgumentException {
|
||||||
|
|
||||||
|
this (name, server, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an application with the given name, server instance, app and
|
||||||
|
* db directories.
|
||||||
|
*/
|
||||||
|
public Application (String name, Server server, File customAppDir, File customDbDir)
|
||||||
throws RemoteException, IllegalArgumentException {
|
throws RemoteException, IllegalArgumentException {
|
||||||
|
|
||||||
if (name == null || name.trim().length() == 0)
|
if (name == null || name.trim().length() == 0)
|
||||||
throw new IllegalArgumentException ("Invalid application name: "+name);
|
throw new IllegalArgumentException ("Invalid application name: "+name);
|
||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.home = home;
|
appDir = customAppDir;
|
||||||
|
dbDir = customDbDir;
|
||||||
|
|
||||||
|
// system-wide properties, default to null
|
||||||
|
Properties sysProps, sysDbProps;
|
||||||
|
sysProps = sysDbProps = null;
|
||||||
|
|
||||||
|
if (server != null) {
|
||||||
|
home = server.getHopHome ();
|
||||||
|
// if appDir and dbDir weren't explicitely passed, use the
|
||||||
|
// standard subdirectories of the Hop home directory
|
||||||
|
if (appDir == null) {
|
||||||
|
appDir = new File (home, "apps");
|
||||||
|
appDir = new File (appDir, name);
|
||||||
|
}
|
||||||
|
if (dbDir == null) {
|
||||||
|
dbDir = new File (home, "db");
|
||||||
|
dbDir = new File (dbDir, name);
|
||||||
|
}
|
||||||
|
// get system-wide properties
|
||||||
|
sysProps = server.getProperties ();
|
||||||
|
sysDbProps = server.getDbProperties ();
|
||||||
|
}
|
||||||
|
// create the directories if they do not exist already
|
||||||
|
if (!appDir.exists())
|
||||||
|
appDir.mkdirs ();
|
||||||
|
if (!dbDir.exists())
|
||||||
|
dbDir.mkdirs ();
|
||||||
|
|
||||||
// give the Helma Thread group a name so the threads can be recognized
|
// give the Helma Thread group a name so the threads can be recognized
|
||||||
threadgroup = new ThreadGroup ("TX-"+name);
|
threadgroup = new ThreadGroup ("TX-"+name);
|
||||||
|
|
||||||
// check the system props to see if custom app directory is set.
|
|
||||||
// otherwise use <home>/apps/<appname>
|
|
||||||
String appHome = null;
|
|
||||||
if (sysProps != null)
|
|
||||||
appHome = sysProps.getProperty ("appHome");
|
|
||||||
if (appHome != null && !"".equals (appHome.trim()))
|
|
||||||
appDir = new File (appHome);
|
|
||||||
else
|
|
||||||
appDir = new File (home, "apps");
|
|
||||||
appDir = new File (appDir, name);
|
|
||||||
if (!appDir.exists())
|
|
||||||
appDir.mkdirs ();
|
|
||||||
|
|
||||||
// check the system props to see if custom embedded db directory is set.
|
|
||||||
// otherwise use <home>/db/<appname>
|
|
||||||
String dbHome = null;
|
|
||||||
if (sysProps != null)
|
|
||||||
dbHome = sysProps.getProperty ("dbHome");
|
|
||||||
if (dbHome != null && !"".equals (dbHome.trim()))
|
|
||||||
dbDir = new File (dbHome);
|
|
||||||
else
|
|
||||||
dbDir = new File (home, "db");
|
|
||||||
dbDir = new File (dbDir, name);
|
|
||||||
if (!dbDir.exists())
|
|
||||||
dbDir.mkdirs ();
|
|
||||||
|
|
||||||
// create app-level properties
|
// create app-level properties
|
||||||
File propfile = new File (appDir, "app.properties");
|
File propfile = new File (appDir, "app.properties");
|
||||||
props = new SystemProperties (propfile.getAbsolutePath (), sysProps);
|
props = new SystemProperties (propfile.getAbsolutePath (), sysProps);
|
||||||
|
@ -183,20 +197,18 @@ public final class Application
|
||||||
dbProps = new SystemProperties (dbpropfile.getAbsolutePath (), sysDbProps);
|
dbProps = new SystemProperties (dbpropfile.getAbsolutePath (), sysDbProps);
|
||||||
|
|
||||||
// the passwd file, to be used with the authenticate() function
|
// the passwd file, to be used with the authenticate() function
|
||||||
File pwf = new File (home, "passwd");
|
// File pwf = new File (home, "passwd");
|
||||||
CryptFile parentpwfile = new CryptFile (pwf, null);
|
// CryptFile parentpwfile = new CryptFile (pwf, null);
|
||||||
pwf = new File (appDir, "passwd");
|
File pwf = new File (appDir, "passwd");
|
||||||
pwfile = new CryptFile (pwf, parentpwfile);
|
CryptFile pwfile = new CryptFile (pwf, null);
|
||||||
|
|
||||||
// the properties that map java class names to prototype names
|
// the properties that map java class names to prototype names
|
||||||
classMapping = new SystemProperties (new File (appDir, "class.properties").getAbsolutePath ());
|
File classMappingFile = new File (appDir, "class.properties");
|
||||||
|
classMapping = new SystemProperties (classMappingFile.getAbsolutePath ());
|
||||||
|
|
||||||
// get class name of root object if defined. Otherwise native Helma objectmodel will be used.
|
// get class name of root object if defined. Otherwise native Helma objectmodel will be used.
|
||||||
rootObjectClass = classMapping.getProperty ("root");
|
rootObjectClass = classMapping.getProperty ("root");
|
||||||
|
|
||||||
// the properties that map allowed public skin extensions to content types
|
|
||||||
skinExtensions = new SystemProperties (new File (appDir, "mime.properties").getAbsolutePath ());
|
|
||||||
|
|
||||||
// character encoding to be used for responses
|
// character encoding to be used for responses
|
||||||
charset = props.getProperty ("charset", "ISO-8859-1");
|
charset = props.getProperty ("charset", "ISO-8859-1");
|
||||||
|
|
||||||
|
@ -206,12 +218,9 @@ public final class Application
|
||||||
|
|
||||||
try {
|
try {
|
||||||
requestTimeout = Long.parseLong (props.getProperty ("requestTimeout", "60"))*1000l;
|
requestTimeout = Long.parseLong (props.getProperty ("requestTimeout", "60"))*1000l;
|
||||||
} catch (Exception ignore) { }
|
} catch (Exception ignore) {
|
||||||
|
// go with default value
|
||||||
templateExtension = props.getProperty ("templateExtension", ".hsp");
|
}
|
||||||
scriptExtension = props.getProperty ("scriptExtension", ".js");
|
|
||||||
actionExtension = props.getProperty ("actionExtension", ".hac");
|
|
||||||
skinExtension = ".skin";
|
|
||||||
|
|
||||||
sessions = new Hashtable ();
|
sessions = new Hashtable ();
|
||||||
dbMappings = new Hashtable ();
|
dbMappings = new Hashtable ();
|
||||||
|
@ -1032,9 +1041,7 @@ public final class Application
|
||||||
*/
|
*/
|
||||||
public Logger getLogger (String logname) {
|
public Logger getLogger (String logname) {
|
||||||
Logger log = null;
|
Logger log = null;
|
||||||
String logDir = props.getProperty ("logdir");
|
String logDir = props.getProperty ("logdir", "log");
|
||||||
if (logDir == null)
|
|
||||||
logDir = "log";
|
|
||||||
// allow log to be redirected to System.out by setting logdir to "console"
|
// allow log to be redirected to System.out by setting logdir to "console"
|
||||||
if ("console".equalsIgnoreCase (logDir))
|
if ("console".equalsIgnoreCase (logDir))
|
||||||
return new Logger (System.out);
|
return new Logger (System.out);
|
||||||
|
|
|
@ -25,7 +25,11 @@ public final class TypeManager {
|
||||||
long lastCheck = 0;
|
long lastCheck = 0;
|
||||||
boolean rewire;
|
boolean rewire;
|
||||||
|
|
||||||
static String[] standardTypes = {"user", "global", "root", "hopobject"};
|
final static String[] standardTypes = {"user", "global", "root", "hopobject"};
|
||||||
|
final static String templateExtension = ".hsp";
|
||||||
|
final static String scriptExtension = ".js";
|
||||||
|
final static String actionExtension = ".hac";
|
||||||
|
final static String skinExtension = ".skin";
|
||||||
|
|
||||||
public TypeManager (Application app) {
|
public TypeManager (Application app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
|
@ -224,8 +228,8 @@ public final class TypeManager {
|
||||||
for (int i=0; i<list.length; i++) {
|
for (int i=0; i<list.length; i++) {
|
||||||
String fn = list[i];
|
String fn = list[i];
|
||||||
if (!proto.updatables.containsKey (fn)) {
|
if (!proto.updatables.containsKey (fn)) {
|
||||||
if (fn.endsWith (app.templateExtension) || fn.endsWith (app.scriptExtension) ||
|
if (fn.endsWith (templateExtension) || fn.endsWith (scriptExtension) ||
|
||||||
fn.endsWith (app.actionExtension) || fn.endsWith (app.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+"]");
|
||||||
|
@ -249,15 +253,15 @@ public final class TypeManager {
|
||||||
if (dot < 0)
|
if (dot < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (proto.updatables.containsKey (fn) || !(fn.endsWith (app.templateExtension) || fn.endsWith (app.scriptExtension) ||
|
if (proto.updatables.containsKey (fn) || !(fn.endsWith (templateExtension) || fn.endsWith (scriptExtension) ||
|
||||||
fn.endsWith (app.actionExtension) || fn.endsWith (app.skinExtension) || "type.properties".equalsIgnoreCase (fn))) {
|
fn.endsWith (actionExtension) || fn.endsWith (skinExtension) || "type.properties".equalsIgnoreCase (fn))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String tmpname = list[i].substring(0, dot);
|
String tmpname = list[i].substring(0, dot);
|
||||||
File tmpfile = new File (dir, list[i]);
|
File tmpfile = new File (dir, list[i]);
|
||||||
|
|
||||||
if (list[i].endsWith (app.templateExtension)) {
|
if (list[i].endsWith (templateExtension)) {
|
||||||
try {
|
try {
|
||||||
Template t = new Template (tmpfile, tmpname, proto);
|
Template t = new Template (tmpfile, tmpname, proto);
|
||||||
proto.updatables.put (list[i], t);
|
proto.updatables.put (list[i], t);
|
||||||
|
@ -266,7 +270,7 @@ public final class TypeManager {
|
||||||
app.logEvent ("Error updating prototype: "+x);
|
app.logEvent ("Error updating prototype: "+x);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (list[i].endsWith (app.scriptExtension)) {
|
} else if (list[i].endsWith (scriptExtension)) {
|
||||||
try {
|
try {
|
||||||
FunctionFile ff = new FunctionFile (tmpfile, tmpname, proto);
|
FunctionFile ff = new FunctionFile (tmpfile, tmpname, proto);
|
||||||
proto.updatables.put (list[i], ff);
|
proto.updatables.put (list[i], ff);
|
||||||
|
@ -275,7 +279,7 @@ public final class TypeManager {
|
||||||
app.logEvent ("Error updating prototype: "+x);
|
app.logEvent ("Error updating prototype: "+x);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (list[i].endsWith (app.actionExtension)) {
|
} else if (list[i].endsWith (actionExtension)) {
|
||||||
try {
|
try {
|
||||||
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
|
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
|
||||||
proto.updatables.put (list[i], af);
|
proto.updatables.put (list[i], af);
|
||||||
|
@ -284,7 +288,7 @@ public final class TypeManager {
|
||||||
app.logEvent ("Error updating prototype: "+x);
|
app.logEvent ("Error updating prototype: "+x);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (list[i].endsWith (app.skinExtension)) {
|
} else if (list[i].endsWith (skinExtension)) {
|
||||||
SkinFile sf = new SkinFile (tmpfile, tmpname, proto);
|
SkinFile sf = new SkinFile (tmpfile, tmpname, proto);
|
||||||
proto.updatables.put (list[i], sf);
|
proto.updatables.put (list[i], sf);
|
||||||
proto.skins.put (tmpname, sf);
|
proto.skins.put (tmpname, sf);
|
||||||
|
|
|
@ -16,7 +16,6 @@ import helma.framework.core.*;
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.servlet.*;
|
import helma.servlet.*;
|
||||||
import helma.util.SystemProperties;
|
import helma.util.SystemProperties;
|
||||||
// import Acme.Serve.*;
|
|
||||||
import org.mortbay.http.*;
|
import org.mortbay.http.*;
|
||||||
import org.mortbay.http.handler.*;
|
import org.mortbay.http.handler.*;
|
||||||
import org.mortbay.jetty.servlet.*;
|
import org.mortbay.jetty.servlet.*;
|
||||||
|
@ -37,7 +36,6 @@ public class ApplicationManager {
|
||||||
private SystemProperties props;
|
private SystemProperties props;
|
||||||
private Server server;
|
private Server server;
|
||||||
private long lastModified;
|
private long lastModified;
|
||||||
// EmbeddedTomcat tomcat;
|
|
||||||
|
|
||||||
public ApplicationManager (int port, File hopHome, SystemProperties props, Server server) {
|
public ApplicationManager (int port, File hopHome, SystemProperties props, Server server) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
@ -104,7 +102,14 @@ public class ApplicationManager {
|
||||||
void start (String appName) {
|
void start (String appName) {
|
||||||
Server.getLogger().log ("Building application "+appName);
|
Server.getLogger().log ("Building application "+appName);
|
||||||
try {
|
try {
|
||||||
Application app = new Application (appName, hopHome, Server.sysProps, Server.dbProps);
|
// check if application and db dirs are set, otherwise go with
|
||||||
|
// the defaults, passing null dirs to the constructor.
|
||||||
|
String appDirName = props.getProperty (appName+".appdir");
|
||||||
|
File appDir = appDirName == null ? null : new File (appDirName);
|
||||||
|
String dbDirName = props.getProperty (appName+".dbdir");
|
||||||
|
File dbDir = dbDirName == null ? null : new File (dbDirName);
|
||||||
|
// create the application instance
|
||||||
|
Application app = new Application (appName, server, appDir, dbDir);
|
||||||
applications.put (appName, app);
|
applications.put (appName, app);
|
||||||
// the application is started later in the register method, when it's bound
|
// the application is started later in the register method, when it's bound
|
||||||
app.init ();
|
app.init ();
|
||||||
|
|
|
@ -12,21 +12,40 @@ import helma.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standalone servlet client that runs a Helma application all by itself
|
* Standalone servlet client that runs a Helma application all by itself
|
||||||
* in embedded mode without relying on helma.main.Server.
|
* in embedded mode without relying on a central instance of helma.main.Server
|
||||||
|
* to start and manage the application.
|
||||||
|
*
|
||||||
|
* StandaloneServletClient takes the following init parameters:
|
||||||
|
* <ul>
|
||||||
|
* <li> application - the application name </li>
|
||||||
|
* <li> appdir - the path of the application home directory </li>
|
||||||
|
* <li> dbdir - the path of the embedded XML data store </li>
|
||||||
|
* </ul>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class StandaloneServletClient extends AbstractServletClient {
|
public final class StandaloneServletClient extends AbstractServletClient {
|
||||||
|
|
||||||
private Application app = null;
|
private Application app = null;
|
||||||
private String appName;
|
private String appName;
|
||||||
private String serverProps;
|
private String appDir;
|
||||||
|
private String dbDir;
|
||||||
|
|
||||||
|
|
||||||
public void init (ServletConfig init) throws ServletException {
|
public void init (ServletConfig init) throws ServletException {
|
||||||
super.init (init);
|
super.init (init);
|
||||||
|
|
||||||
appName = init.getInitParameter ("application");
|
appName = init.getInitParameter ("application");
|
||||||
serverProps = init.getInitParameter ("serverprops");
|
if (appName == null || appName.trim().length() == 0)
|
||||||
}
|
throw new ServletException ("application parameter not specified");
|
||||||
|
|
||||||
|
appDir = init.getInitParameter ("appdir");
|
||||||
|
if (appDir == null || appDir.trim().length() == 0)
|
||||||
|
throw new ServletException ("appdir parameter not specified");
|
||||||
|
|
||||||
|
dbDir = init.getInitParameter ("dbdir");
|
||||||
|
if (dbDir == null || dbDir.trim().length() == 0)
|
||||||
|
throw new ServletException ("dbdir parameter not specified");
|
||||||
|
}
|
||||||
|
|
||||||
IRemoteApp getApp (String appID) {
|
IRemoteApp getApp (String appID) {
|
||||||
if (app == null)
|
if (app == null)
|
||||||
|
@ -42,14 +61,13 @@ public final class StandaloneServletClient extends AbstractServletClient {
|
||||||
if (app != null)
|
if (app != null)
|
||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
File propfile = new File (serverProps);
|
File appHome = new File (appDir);
|
||||||
File hopHome = new File (propfile.getParent());
|
File dbHome = new File (dbDir);
|
||||||
SystemProperties sysProps = new SystemProperties (propfile.getAbsolutePath());
|
app = new Application (appName, appHome, dbHome);
|
||||||
app = new Application (appName, hopHome, sysProps, null);
|
|
||||||
app.init ();
|
app.init ();
|
||||||
app.start ();
|
app.start ();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
System.err.println ("Error starting Application "+appName+": "+x);
|
log ("Error starting Application "+appName+": "+x);
|
||||||
x.printStackTrace ();
|
x.printStackTrace ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +82,7 @@ public final class StandaloneServletClient extends AbstractServletClient {
|
||||||
try {
|
try {
|
||||||
app.stop ();
|
app.stop ();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
System.err.println ("Error shutting down app "+app.getName()+": ");
|
log ("Error shutting down app "+app.getName()+": ");
|
||||||
x.printStackTrace ();
|
x.printStackTrace ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue