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
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue