initial check in of new helma.main package
This commit is contained in:
parent
4dea0349e2
commit
232f1b37bd
3 changed files with 491 additions and 0 deletions
145
src/helma/main/ApplicationManager.java
Normal file
145
src/helma/main/ApplicationManager.java
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
// ApplicationManager.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
package helma.main;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.rmi.*;
|
||||||
|
import java.rmi.server.*;
|
||||||
|
import helma.framework.*;
|
||||||
|
import helma.framework.core.*;
|
||||||
|
import helma.objectmodel.*;
|
||||||
|
import helma.servlet.*;
|
||||||
|
import helma.util.SystemProperties;
|
||||||
|
import Acme.Serve.*;
|
||||||
|
import javax.servlet.Servlet;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is responsible for starting and stopping Helma applications.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ApplicationManager {
|
||||||
|
|
||||||
|
private Hashtable applications;
|
||||||
|
private int port;
|
||||||
|
private File hopHome;
|
||||||
|
private SystemProperties props;
|
||||||
|
private Server server;
|
||||||
|
private long lastModified;
|
||||||
|
|
||||||
|
public ApplicationManager (int port, File hopHome, SystemProperties props, Server server) {
|
||||||
|
this.port = port;
|
||||||
|
this.hopHome = hopHome;
|
||||||
|
this.props = props;
|
||||||
|
this.server = server;
|
||||||
|
applications = new Hashtable ();
|
||||||
|
lastModified = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// regularely check applications property file to create and start new applications
|
||||||
|
protected void checkForChanges () {
|
||||||
|
if (props.lastModified () > lastModified) {
|
||||||
|
try {
|
||||||
|
for (Enumeration e = props.keys(); e.hasMoreElements (); ) {
|
||||||
|
String appName = (String) e.nextElement ();
|
||||||
|
if (applications.get (appName) == null) {
|
||||||
|
start (appName);
|
||||||
|
register (appName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// then stop deleted ones
|
||||||
|
for (Enumeration e = applications.keys(); e.hasMoreElements (); ) {
|
||||||
|
String appName = (String) e.nextElement ();
|
||||||
|
if (!props.containsKey (appName)) {
|
||||||
|
stop (appName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception mx) {
|
||||||
|
Server.getLogger().log ("Error starting applications: "+mx);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastModified = System.currentTimeMillis ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void start (String appName) {
|
||||||
|
Server.getLogger().log ("Building application "+appName);
|
||||||
|
try {
|
||||||
|
Application app = new Application (appName, Server.sysProps, Server.dbProps, hopHome);
|
||||||
|
applications.put (appName, app);
|
||||||
|
// if we're running with the embedded web server, set app base uri to /appname
|
||||||
|
if (server.websrv != null)
|
||||||
|
app.setBaseURI ("/"+java.net.URLEncoder.encode (appName));
|
||||||
|
// the application is initialized later in the register method, when it's bound
|
||||||
|
app.start ();
|
||||||
|
} catch (Exception x) {
|
||||||
|
Server.getLogger().log ("Error creating application "+appName+": "+x);
|
||||||
|
x.printStackTrace ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stop (String appName) {
|
||||||
|
Server.getLogger().log ("Stopping application "+appName);
|
||||||
|
try {
|
||||||
|
Application app = (Application) applications.get (appName);
|
||||||
|
if (server.websrv == null) {
|
||||||
|
Naming.unbind ("//:"+port+"/"+appName);
|
||||||
|
} else {
|
||||||
|
server.websrv.removeServlet ("/"+appName+"/");
|
||||||
|
server.websrv.removeServlet ("/"+appName+"/*");
|
||||||
|
}
|
||||||
|
app.stop ();
|
||||||
|
Server.getLogger().log ("Unregistered application "+appName);
|
||||||
|
} catch (Exception x) {
|
||||||
|
Server.getLogger().log ("Couldn't unregister app: "+x);
|
||||||
|
}
|
||||||
|
applications.remove (appName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void register (String appName) {
|
||||||
|
try {
|
||||||
|
Server.getLogger().log ("Binding application "+appName);
|
||||||
|
Application app = (Application) applications.get (appName);
|
||||||
|
// app.start ();
|
||||||
|
if (server.websrv == null) {
|
||||||
|
Naming.rebind ("//:"+port+"/"+appName, app);
|
||||||
|
} else {
|
||||||
|
AcmeServletClient servlet = new AcmeServletClient (app);
|
||||||
|
server.websrv.addServlet ("/"+appName+"/", servlet);
|
||||||
|
server.websrv.addServlet ("/"+appName+"/*", servlet);
|
||||||
|
}
|
||||||
|
} catch (Exception x) {
|
||||||
|
Server.getLogger().log ("Couldn't register and start app: "+x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startAll () {
|
||||||
|
try {
|
||||||
|
for (Enumeration e = props.keys(); e.hasMoreElements (); ) {
|
||||||
|
String appName = (String) e.nextElement ();
|
||||||
|
start (appName);
|
||||||
|
}
|
||||||
|
for (Enumeration e = props.keys(); e.hasMoreElements (); ) {
|
||||||
|
String appName = (String) e.nextElement ();
|
||||||
|
register (appName);
|
||||||
|
}
|
||||||
|
if (server.websrv != null) {
|
||||||
|
File staticContent = new File (server.getHopHome(), "static");
|
||||||
|
Server.getLogger().log("Serving static content from "+staticContent.getAbsolutePath());
|
||||||
|
AcmeFileServlet fsrv = new AcmeFileServlet (staticContent);
|
||||||
|
server.websrv.addServlet ("/static/", fsrv);
|
||||||
|
server.websrv.addServlet ("/static/*", fsrv);
|
||||||
|
}
|
||||||
|
lastModified = System.currentTimeMillis ();
|
||||||
|
} catch (Exception mx) {
|
||||||
|
Server.getLogger().log ("Error starting applications: "+mx);
|
||||||
|
mx.printStackTrace ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
42
src/helma/main/HopSocketFactory.java
Normal file
42
src/helma/main/HopSocketFactory.java
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// HopSocketFactory.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1999-2000
|
||||||
|
|
||||||
|
|
||||||
|
package helma.main;
|
||||||
|
|
||||||
|
import helma.util.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.rmi.server.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An RMI socket factory that has a "paranoid" option to filter clients.
|
||||||
|
* We only do direct connections, no HTTP proxy stuff, since this is
|
||||||
|
* server-to-server.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class HopSocketFactory extends RMISocketFactory {
|
||||||
|
|
||||||
|
private InetAddressFilter filter;
|
||||||
|
|
||||||
|
public HopSocketFactory () {
|
||||||
|
filter = new InetAddressFilter ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAddress (String address) {
|
||||||
|
try {
|
||||||
|
filter.addAddress (address);
|
||||||
|
} catch (IOException x) {
|
||||||
|
Server.getLogger().log ("Could not add "+address+" to Socket Filter: invalid address.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Socket createSocket(String host, int port) throws IOException {
|
||||||
|
return new Socket (host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerSocket createServerSocket(int port) throws IOException {
|
||||||
|
return new ParanoidServerSocket (port, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
304
src/helma/main/Server.java
Normal file
304
src/helma/main/Server.java
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
// Server.java
|
||||||
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
|
package helma.main;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.rmi.*;
|
||||||
|
import java.rmi.server.*;
|
||||||
|
import java.rmi.registry.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.Locale;
|
||||||
|
import helma.objectmodel.*;
|
||||||
|
import helma.objectmodel.db.DbSource;
|
||||||
|
import helma.framework.*;
|
||||||
|
import helma.framework.core.*;
|
||||||
|
import helma.xmlrpc.*;
|
||||||
|
import helma.util.*;
|
||||||
|
import com.sleepycat.db.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helma server main class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Server implements Runnable {
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean useTransactions, paranoid;
|
||||||
|
|
||||||
|
private ApplicationManager appManager;
|
||||||
|
|
||||||
|
private Thread mainThread;
|
||||||
|
|
||||||
|
public static String dbFilename = "hop.db";
|
||||||
|
static String propfile;
|
||||||
|
static String dbPropfile = "db.properties";
|
||||||
|
static String appsPropfile;
|
||||||
|
static SystemProperties appsProps;
|
||||||
|
static SystemProperties dbProps;
|
||||||
|
static SystemProperties sysProps;
|
||||||
|
static int port = 5055;
|
||||||
|
static int webport = 0;
|
||||||
|
|
||||||
|
Acme.Serve.Serve websrv;
|
||||||
|
|
||||||
|
static Hashtable dbSources;
|
||||||
|
|
||||||
|
protected static File hopHome = null;
|
||||||
|
|
||||||
|
private static Logger logger;
|
||||||
|
|
||||||
|
protected static WebServer xmlrpc;
|
||||||
|
|
||||||
|
|
||||||
|
public static void main (String args[]) throws IOException {
|
||||||
|
|
||||||
|
// check if we are running on a Java 2 VM - otherwise exit with an error message
|
||||||
|
String jversion = System.getProperty ("java.version");
|
||||||
|
if (jversion == null || jversion.startsWith ("1.1") || jversion.startsWith ("1.0")) {
|
||||||
|
System.err.println ("This version of Helma requires Java 1.2 or greater.");
|
||||||
|
if (jversion == null) // don't think this will ever happen, but you never know
|
||||||
|
System.err.println ("Your Java Runtime did not provide a version number. Please update to a more recent version.");
|
||||||
|
else
|
||||||
|
System.err.println ("Your Java Runtime is version "+jversion+". Please update to a more recent version.");
|
||||||
|
System.exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String homeDir = null;
|
||||||
|
|
||||||
|
boolean usageError = false;
|
||||||
|
|
||||||
|
useTransactions = true;
|
||||||
|
|
||||||
|
for (int i=0; i<args.length; i++) {
|
||||||
|
if (args[i].equals ("-h") && i+1<args.length)
|
||||||
|
homeDir = args[++i];
|
||||||
|
else if (args[i].equals ("-f") && i+1<args.length)
|
||||||
|
propfile = args[++i];
|
||||||
|
else if (args[i].equals ("-t"))
|
||||||
|
useTransactions = false;
|
||||||
|
else if (args[i].equals ("-p") && i+1<args.length) {
|
||||||
|
try {
|
||||||
|
port = Integer.parseInt (args[++i]);
|
||||||
|
} catch (Exception portx) {
|
||||||
|
usageError = true;
|
||||||
|
}
|
||||||
|
} else if (args[i].equals ("-w") && i+1<args.length) {
|
||||||
|
try {
|
||||||
|
webport = Integer.parseInt (args[++i]);
|
||||||
|
} catch (Exception portx) {
|
||||||
|
usageError = true;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
usageError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usageError ) {
|
||||||
|
System.out.println ("usage: java helma.objectmodel.db.Server [-h dir] [-f file] [-p port] [-w port] [-t]");
|
||||||
|
System.out.println (" -h dir Specify hop home directory");
|
||||||
|
System.out.println (" -f file Specify server.properties file");
|
||||||
|
System.out.println (" -p port Specify TCP port number");
|
||||||
|
System.out.println (" -w port Start embedded Web server on that port");
|
||||||
|
System.out.println (" -t Disable Berkeley DB Transactions");
|
||||||
|
getLogger().log ("Usage Error - exiting");
|
||||||
|
System.exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
new Server (homeDir);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Server (String home) {
|
||||||
|
|
||||||
|
String homeDir = home;
|
||||||
|
|
||||||
|
// get main property file from home dir or vice versa, depending on what we have.
|
||||||
|
// get property file from hopHome
|
||||||
|
if (propfile == null) {
|
||||||
|
if (homeDir != null)
|
||||||
|
propfile = new File (homeDir, "server.properties").getAbsolutePath ();
|
||||||
|
else
|
||||||
|
propfile = new File ("server.properties").getAbsolutePath ();
|
||||||
|
}
|
||||||
|
|
||||||
|
sysProps = new SystemProperties (propfile);
|
||||||
|
// get hopHome from property file
|
||||||
|
if (homeDir == null)
|
||||||
|
homeDir = sysProps.getProperty ("hophome");
|
||||||
|
if (homeDir == null)
|
||||||
|
homeDir = new File (propfile).getParent ();
|
||||||
|
|
||||||
|
// create hopHome File object
|
||||||
|
hopHome = new File (homeDir);
|
||||||
|
|
||||||
|
getLogger().log ("propfile = "+propfile);
|
||||||
|
getLogger().log ("hopHome = "+hopHome);
|
||||||
|
|
||||||
|
|
||||||
|
File helper = new File (hopHome, "db.properties");
|
||||||
|
dbPropfile = helper.getAbsolutePath ();
|
||||||
|
dbProps = new SystemProperties (dbPropfile);
|
||||||
|
DbSource.setDefaultProps (dbProps);
|
||||||
|
getLogger().log ("dbPropfile = "+dbPropfile);
|
||||||
|
|
||||||
|
appsPropfile = sysProps.getProperty ("appsPropFile");
|
||||||
|
if (appsPropfile != null && !"".equals (appsPropfile.trim()))
|
||||||
|
helper = new File (appsPropfile);
|
||||||
|
else
|
||||||
|
helper = new File (hopHome, "apps.properties");
|
||||||
|
appsPropfile = helper.getAbsolutePath ();
|
||||||
|
getLogger().log ("appsPropfile = "+appsPropfile);
|
||||||
|
|
||||||
|
paranoid = "true".equalsIgnoreCase (sysProps.getProperty ("paranoid"));
|
||||||
|
|
||||||
|
String language = sysProps.getProperty ("language");
|
||||||
|
String country = sysProps.getProperty ("country");
|
||||||
|
String timezone = sysProps.getProperty ("timezone");
|
||||||
|
|
||||||
|
if (language != null && country != null)
|
||||||
|
Locale.setDefault (new Locale (language, country));
|
||||||
|
if (timezone != null)
|
||||||
|
TimeZone.setDefault (TimeZone.getTimeZone (timezone));
|
||||||
|
|
||||||
|
getLogger().log ("Locale = "+Locale.getDefault());
|
||||||
|
getLogger().log ("TimeZone = "+TimeZone.getDefault().getDisplayName (Locale.getDefault ()));
|
||||||
|
|
||||||
|
dbSources = new Hashtable ();
|
||||||
|
|
||||||
|
try {
|
||||||
|
checkRunning (); // check if a server is already running with this db
|
||||||
|
} catch (Exception running) {
|
||||||
|
System.out.println (running.getMessage ());
|
||||||
|
System.exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nmgr = new NodeManager (this, sysProps);
|
||||||
|
|
||||||
|
mainThread = new Thread (this);
|
||||||
|
mainThread.start ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run () {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// start embedded web server if port is specified
|
||||||
|
if (webport > 0) {
|
||||||
|
websrv = new Acme.Serve.Serve (webport, sysProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
String xmlparser = sysProps.getProperty ("xmlparser");
|
||||||
|
if (xmlparser != null)
|
||||||
|
XmlRpc.setDriver (xmlparser);
|
||||||
|
// XmlRpc.setDebug (true);
|
||||||
|
xmlrpc = new WebServer (port+1);
|
||||||
|
if (paranoid) {
|
||||||
|
xmlrpc.setParanoid (true);
|
||||||
|
String xallow = sysProps.getProperty ("allowXmlRpc");
|
||||||
|
if (xallow != null) {
|
||||||
|
StringTokenizer st = new StringTokenizer (xallow, " ,;");
|
||||||
|
while (st.hasMoreTokens ())
|
||||||
|
xmlrpc.acceptClient (st.nextToken ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getLogger().log ("Starting XML-RPC server on port "+(port+1));
|
||||||
|
|
||||||
|
// the following seems not to be necessary after all ...
|
||||||
|
// System.setSecurityManager(new RMISecurityManager());
|
||||||
|
if (paranoid) {
|
||||||
|
HopSocketFactory factory = new HopSocketFactory ();
|
||||||
|
String rallow = sysProps.getProperty ("allowWeb");
|
||||||
|
if (rallow != null) {
|
||||||
|
StringTokenizer st = new StringTokenizer (rallow, " ,;");
|
||||||
|
while (st.hasMoreTokens ())
|
||||||
|
factory.addAddress (st.nextToken ());
|
||||||
|
}
|
||||||
|
RMISocketFactory.setSocketFactory (factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (websrv == null) {
|
||||||
|
getLogger().log ("Starting server on port "+port);
|
||||||
|
LocateRegistry.createRegistry (port);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// start application framework
|
||||||
|
appsProps = new SystemProperties (appsPropfile);
|
||||||
|
appManager = new ApplicationManager (port, hopHome, appsProps, this);
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Exception gx) {
|
||||||
|
getLogger().log ("Error initializing embedded database: "+gx);
|
||||||
|
gx.printStackTrace ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start applications
|
||||||
|
appManager.startAll ();
|
||||||
|
|
||||||
|
// start embedded web server
|
||||||
|
if (websrv != null) {
|
||||||
|
Thread webthread = new Thread (websrv, "WebServer");
|
||||||
|
webthread.start ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
while (Thread.currentThread () == mainThread) {
|
||||||
|
try {
|
||||||
|
mainThread.sleep (3000l);
|
||||||
|
} catch (InterruptedException ie) {}
|
||||||
|
try {
|
||||||
|
appManager.checkForChanges ();
|
||||||
|
} catch (Exception x) {
|
||||||
|
getLogger().log ("Caught in app manager loop: "+x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Logger getLogger () {
|
||||||
|
if (logger == null) {
|
||||||
|
String logDir = sysProps.getProperty ("logdir");
|
||||||
|
if (logDir == null || "console".equalsIgnoreCase (logDir)) {
|
||||||
|
logger = new Logger (System.out);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
File helper = new File (logDir);
|
||||||
|
if (hopHome != null && !helper.isAbsolute ())
|
||||||
|
helper = new File (hopHome, logDir);
|
||||||
|
logDir = helper.getAbsolutePath ();
|
||||||
|
logger = new Logger (logDir, "hop");
|
||||||
|
} catch (IOException iox) {
|
||||||
|
System.err.println ("Could not create Logger for log/hop: "+iox);
|
||||||
|
// fallback to System.out
|
||||||
|
logger = new Logger (System.out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getHopHome () {
|
||||||
|
return hopHome;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebServer getXmlRpcServer() {
|
||||||
|
return xmlrpc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void checkRunning () throws Exception {
|
||||||
|
try {
|
||||||
|
java.net.Socket socket = new java.net.Socket ("localhost", port);
|
||||||
|
} catch (Exception x) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// if we got so far, another server is already running on this port and db
|
||||||
|
throw new Exception ("Error: Server already running on this port");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue