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:
hns 2002-08-02 10:27:31 +00:00
parent c044ab86ab
commit 65b8d6b2c4
4 changed files with 121 additions and 87 deletions

View file

@ -27,13 +27,18 @@ import java.rmi.server.*;
* requests from the Web server or XML-RPC port and dispatches them to
* the evaluators.
*/
public final class Application
public final class Application
extends UnicastRemoteObject
implements IRemoteApp, IPathElement, IReplicatedApp, Runnable {
// the name of this application
private String name;
// properties and db-properties
SystemProperties props, dbProps;
// home, app and data directories
File home, appDir, dbDir;
// this application's node manager
protected NodeManager nmgr;
// the root of the website, if a custom root object is defined.
@ -72,6 +77,7 @@ public final class Application
Hashtable dbMappings;
Hashtable dbSources;
// internal worker thread for scheduler, session cleanup etc.
Thread worker;
long requestTimeout = 60000; // 60 seconds for request timeout.
ThreadGroup threadgroup;
@ -82,10 +88,10 @@ public final class Application
// Two logs for each application: events and accesses
Logger eventLog, accessLog;
protected String templateExtension, scriptExtension, actionExtension, skinExtension;
// A transient node that is shared among all evaluators
protected INode cachenode;
// some fields for statistics
protected volatile long requestCount = 0;
protected volatile long xmlrpcCount = 0;
protected volatile long errorCount = 0;
@ -99,9 +105,7 @@ public final class Application
private DbMapping rootMapping, userRootMapping, userMapping;
// boolean checkSubnodes;
// name of respone encoding
// name of response encoding
String charset;
// password file to use for authenticate() function
@ -118,62 +122,72 @@ public final class Application
/**
* Zero argument constructor needed for RMI
*/
public Application () throws RemoteException {
/* public Application () throws RemoteException {
super ();
}
} */
/**
* Build an application with the given name in the home directory. Server-wide properties will
* be created if the files are present, but they don't have to.
* Build an application with the given name in the app directory. No Server-wide
* properties are created or used.
*/
public Application (String name, File home) throws RemoteException, IllegalArgumentException {
this (name, home,
new SystemProperties (new File (home, "server.properties").getAbsolutePath ()),
new SystemProperties (new File (home, "db.properties").getAbsolutePath ()));
public Application (String name, File appDir, File dbDir)
throws RemoteException, IllegalArgumentException {
this (name, null, appDir, dbDir);
}
/**
* 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.
*/
public Application (String name, File home, SystemProperties sysProps, SystemProperties sysDbProps)
throws RemoteException, IllegalArgumentException {
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 {
if (name == null || name.trim().length() == 0)
throw new IllegalArgumentException ("Invalid application 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
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
File propfile = new File (appDir, "app.properties");
props = new SystemProperties (propfile.getAbsolutePath (), sysProps);
@ -183,36 +197,31 @@ public final class Application
dbProps = new SystemProperties (dbpropfile.getAbsolutePath (), sysDbProps);
// the passwd file, to be used with the authenticate() function
File pwf = new File (home, "passwd");
CryptFile parentpwfile = new CryptFile (pwf, null);
pwf = new File (appDir, "passwd");
pwfile = new CryptFile (pwf, parentpwfile);
// File pwf = new File (home, "passwd");
// CryptFile parentpwfile = new CryptFile (pwf, null);
File pwf = new File (appDir, "passwd");
CryptFile pwfile = new CryptFile (pwf, null);
// 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.
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
charset = props.getProperty ("charset", "ISO-8859-1");
debug = "true".equalsIgnoreCase (props.getProperty ("debug"));
// checkSubnodes = !"false".equalsIgnoreCase (props.getProperty ("subnodeChecking"));
try {
requestTimeout = Long.parseLong (props.getProperty ("requestTimeout", "60"))*1000l;
} catch (Exception ignore) { }
templateExtension = props.getProperty ("templateExtension", ".hsp");
scriptExtension = props.getProperty ("scriptExtension", ".js");
actionExtension = props.getProperty ("actionExtension", ".hac");
skinExtension = ".skin";
} catch (Exception ignore) {
// go with default value
}
sessions = new Hashtable ();
dbMappings = new Hashtable ();
dbSources = new Hashtable ();
@ -430,7 +439,7 @@ public final class Application
public ResponseTrans execute (RequestTrans req) {
requestCount += 1;
// get user for this request's session
Session session = checkSession (req.session);
session.touch();
@ -617,7 +626,7 @@ public final class Application
* Return the session currently associated with a given Hop session ID.
* Create a new session if necessary.
*/
public Session checkSession (String sessionID) {
public Session checkSession (String sessionID) {
Session session = getSession(sessionID);
if ( session==null ) {
session = new Session (sessionID, this);
@ -1032,9 +1041,7 @@ public final class Application
*/
public Logger getLogger (String logname) {
Logger log = null;
String logDir = props.getProperty ("logdir");
if (logDir == null)
logDir = "log";
String logDir = props.getProperty ("logdir", "log");
// allow log to be redirected to System.out by setting logdir to "console"
if ("console".equalsIgnoreCase (logDir))
return new Logger (System.out);

View file

@ -25,7 +25,11 @@ public final class TypeManager {
long lastCheck = 0;
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) {
this.app = app;
@ -224,8 +228,8 @@ public final class TypeManager {
for (int i=0; i<list.length; i++) {
String fn = list[i];
if (!proto.updatables.containsKey (fn)) {
if (fn.endsWith (app.templateExtension) || fn.endsWith (app.scriptExtension) ||
fn.endsWith (app.actionExtension) || fn.endsWith (app.skinExtension) ||
if (fn.endsWith (templateExtension) || fn.endsWith (scriptExtension) ||
fn.endsWith (actionExtension) || fn.endsWith (skinExtension) ||
"type.properties".equalsIgnoreCase (fn)) {
needsUpdate = true;
// updatables.add ("[new:"+proto.getName()+"/"+fn+"]");
@ -249,15 +253,15 @@ public final class TypeManager {
if (dot < 0)
continue;
if (proto.updatables.containsKey (fn) || !(fn.endsWith (app.templateExtension) || fn.endsWith (app.scriptExtension) ||
fn.endsWith (app.actionExtension) || fn.endsWith (app.skinExtension) || "type.properties".equalsIgnoreCase (fn))) {
if (proto.updatables.containsKey (fn) || !(fn.endsWith (templateExtension) || fn.endsWith (scriptExtension) ||
fn.endsWith (actionExtension) || fn.endsWith (skinExtension) || "type.properties".equalsIgnoreCase (fn))) {
continue;
}
String tmpname = list[i].substring(0, dot);
File tmpfile = new File (dir, list[i]);
if (list[i].endsWith (app.templateExtension)) {
if (list[i].endsWith (templateExtension)) {
try {
Template t = new Template (tmpfile, tmpname, proto);
proto.updatables.put (list[i], t);
@ -266,7 +270,7 @@ public final class TypeManager {
app.logEvent ("Error updating prototype: "+x);
}
} else if (list[i].endsWith (app.scriptExtension)) {
} else if (list[i].endsWith (scriptExtension)) {
try {
FunctionFile ff = new FunctionFile (tmpfile, tmpname, proto);
proto.updatables.put (list[i], ff);
@ -275,7 +279,7 @@ public final class TypeManager {
app.logEvent ("Error updating prototype: "+x);
}
} else if (list[i].endsWith (app.actionExtension)) {
} else if (list[i].endsWith (actionExtension)) {
try {
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
proto.updatables.put (list[i], af);
@ -284,7 +288,7 @@ public final class TypeManager {
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);
proto.updatables.put (list[i], sf);
proto.skins.put (tmpname, sf);

View file

@ -16,7 +16,6 @@ import helma.framework.core.*;
import helma.objectmodel.*;
import helma.servlet.*;
import helma.util.SystemProperties;
// import Acme.Serve.*;
import org.mortbay.http.*;
import org.mortbay.http.handler.*;
import org.mortbay.jetty.servlet.*;
@ -37,7 +36,6 @@ public class ApplicationManager {
private SystemProperties props;
private Server server;
private long lastModified;
// EmbeddedTomcat tomcat;
public ApplicationManager (int port, File hopHome, SystemProperties props, Server server) {
this.port = port;
@ -104,7 +102,14 @@ public class ApplicationManager {
void start (String appName) {
Server.getLogger().log ("Building application "+appName);
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);
// the application is started later in the register method, when it's bound
app.init ();

View file

@ -12,21 +12,40 @@ import helma.util.*;
/**
* 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 {
private Application app = null;
private String appName;
private String serverProps;
private String appDir;
private String dbDir;
public void init (ServletConfig init) throws ServletException {
super.init (init);
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) {
if (app == null)
@ -42,14 +61,13 @@ public final class StandaloneServletClient extends AbstractServletClient {
if (app != null)
return;
try {
File propfile = new File (serverProps);
File hopHome = new File (propfile.getParent());
SystemProperties sysProps = new SystemProperties (propfile.getAbsolutePath());
app = new Application (appName, hopHome, sysProps, null);
File appHome = new File (appDir);
File dbHome = new File (dbDir);
app = new Application (appName, appHome, dbHome);
app.init ();
app.start ();
} catch (Exception x) {
System.err.println ("Error starting Application "+appName+": "+x);
log ("Error starting Application "+appName+": "+x);
x.printStackTrace ();
}
}
@ -64,7 +82,7 @@ public final class StandaloneServletClient extends AbstractServletClient {
try {
app.stop ();
} catch (Exception x) {
System.err.println ("Error shutting down app "+app.getName()+": ");
log ("Error shutting down app "+app.getName()+": ");
x.printStackTrace ();
}
}