merge in classloader branch
This commit is contained in:
parent
75afb61744
commit
039ab180be
9 changed files with 319 additions and 64 deletions
37
src/helma/framework/core/AppClassLoader.java
Normal file
37
src/helma/framework/core/AppClassLoader.java
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// ApplicationClassLoader.java
|
||||||
|
|
||||||
|
package helma.framework.core;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.security.CodeSource;
|
||||||
|
import java.security.Permission;
|
||||||
|
import java.security.PermissionCollection;
|
||||||
|
import java.security.Permissions;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassLoader subclass with package accessible addURL method.
|
||||||
|
*/
|
||||||
|
public class AppClassLoader extends URLClassLoader {
|
||||||
|
|
||||||
|
private final String appname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a HelmaClassLoader with the given application name and the given URLs
|
||||||
|
*/
|
||||||
|
public AppClassLoader(String appname, URL[] urls) {
|
||||||
|
super ( urls, AppClassLoader.class.getClassLoader());
|
||||||
|
this.appname = appname;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addURL (URL url) {
|
||||||
|
super.addURL (url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppName () {
|
||||||
|
return appname;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import org.apache.xmlrpc.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.rmi.*;
|
import java.rmi.*;
|
||||||
import java.rmi.server.*;
|
import java.rmi.server.*;
|
||||||
|
@ -122,13 +123,6 @@ public final class Application implements IPathElement, Runnable {
|
||||||
private String xmlrpcHandlerName;
|
private String xmlrpcHandlerName;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zero argument constructor needed for RMI
|
|
||||||
*/
|
|
||||||
/* public Application () throws RemoteException {
|
|
||||||
super ();
|
|
||||||
} */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an application with the given name in the app directory. No Server-wide
|
* Build an application with the given name in the app directory. No Server-wide
|
||||||
* properties are created or used.
|
* properties are created or used.
|
||||||
|
@ -224,7 +218,7 @@ public final class Application implements IPathElement, Runnable {
|
||||||
/**
|
/**
|
||||||
* Get the application ready to run, initializing the evaluators and type manager.
|
* Get the application ready to run, initializing the evaluators and type manager.
|
||||||
*/
|
*/
|
||||||
public void init () throws DatabaseException, ScriptingException {
|
public void init () throws DatabaseException, ScriptingException, MalformedURLException {
|
||||||
// scriptingEngine = new helma.scripting.fesi.FesiScriptingEnvironment ();
|
// scriptingEngine = new helma.scripting.fesi.FesiScriptingEnvironment ();
|
||||||
// scriptingEngine.init (this, props);
|
// scriptingEngine.init (this, props);
|
||||||
|
|
||||||
|
@ -540,11 +534,11 @@ public final class Application implements IPathElement, Runnable {
|
||||||
if (rootObject == null) {
|
if (rootObject == null) {
|
||||||
try {
|
try {
|
||||||
if ( classMapping.containsKey("root.factory.class") && classMapping.containsKey("root.factory.method") ) {
|
if ( classMapping.containsKey("root.factory.class") && classMapping.containsKey("root.factory.method") ) {
|
||||||
Class c = Class.forName( classMapping.getProperty("root.factory.class") );
|
Class c = typemgr.loader.loadClass( classMapping.getProperty("root.factory.class") );
|
||||||
Method m = c.getMethod( classMapping.getProperty("root.factory.method"), null );
|
Method m = c.getMethod( classMapping.getProperty("root.factory.method"), null );
|
||||||
rootObject = m.invoke(c, null);
|
rootObject = m.invoke(c, null);
|
||||||
} else {
|
} else {
|
||||||
Class c = Class.forName( classMapping.getProperty("root") );
|
Class c = typemgr.loader.loadClass( classMapping.getProperty("root") );
|
||||||
rootObject = c.newInstance();
|
rootObject = c.newInstance();
|
||||||
}
|
}
|
||||||
} catch ( Exception e ) {
|
} catch ( Exception e ) {
|
||||||
|
|
|
@ -72,13 +72,11 @@ public final class RequestEvaluator implements Runnable {
|
||||||
if (scriptingEngine == null) {
|
if (scriptingEngine == null) {
|
||||||
String engineClassName = app.getProperty (
|
String engineClassName = app.getProperty (
|
||||||
"scripting.engine.factory",
|
"scripting.engine.factory",
|
||||||
"helma.scripting.fesi.FesiEngineFactory");
|
"helma.scripting.fesi.FesiEngine");
|
||||||
try {
|
try {
|
||||||
Class clazz = Class.forName (engineClassName);
|
Class clazz = app.typemgr.loader.loadClass (engineClassName);
|
||||||
Class[] argClasses = {app.getClass(), getClass()};
|
scriptingEngine = (ScriptingEngine) clazz.newInstance ();
|
||||||
Method method = clazz.getMethod ("getEngine", argClasses);
|
scriptingEngine.init (app, this);
|
||||||
Object[] args = {app, this};
|
|
||||||
scriptingEngine = (ScriptingEngine) method.invoke (null, args);
|
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
Throwable t = x;
|
Throwable t = x;
|
||||||
if (x instanceof InvocationTargetException)
|
if (x instanceof InvocationTargetException)
|
||||||
|
|
|
@ -9,7 +9,8 @@ import helma.scripting.*;
|
||||||
import helma.util.*;
|
import helma.util.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type manager periodically checks the prototype definitions for its
|
* The type manager periodically checks the prototype definitions for its
|
||||||
|
@ -20,8 +21,9 @@ public final class TypeManager {
|
||||||
|
|
||||||
Application app;
|
Application app;
|
||||||
File appDir;
|
File appDir;
|
||||||
HashMap prototypes;
|
HashMap prototypes; // map of prototypes
|
||||||
HashMap zipfiles;
|
HashMap zipfiles; // map of zipped script files
|
||||||
|
HashSet jarfiles; // set of Java archives
|
||||||
long lastCheck = 0;
|
long lastCheck = 0;
|
||||||
long appDirMod = 0;
|
long appDirMod = 0;
|
||||||
// a checksum that changes whenever something in the application files changes.
|
// a checksum that changes whenever something in the application files changes.
|
||||||
|
@ -31,6 +33,9 @@ public final class TypeManager {
|
||||||
Prototype hopobjectProto;
|
Prototype hopobjectProto;
|
||||||
// the global prototype
|
// the global prototype
|
||||||
Prototype globalProto;
|
Prototype globalProto;
|
||||||
|
|
||||||
|
// app specific class loader, includes jar files in the app directory
|
||||||
|
AppClassLoader loader;
|
||||||
|
|
||||||
final static String[] standardTypes = {"user", "global", "root", "hopobject"};
|
final static String[] standardTypes = {"user", "global", "root", "hopobject"};
|
||||||
|
|
||||||
|
@ -39,7 +44,7 @@ public final class TypeManager {
|
||||||
final static String actionExtension = ".hac";
|
final static String actionExtension = ".hac";
|
||||||
final static String skinExtension = ".skin";
|
final static String skinExtension = ".skin";
|
||||||
|
|
||||||
public TypeManager (Application app) {
|
public TypeManager (Application app) throws MalformedURLException {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
appDir = app.appDir;
|
appDir = app.appDir;
|
||||||
// make sure the directories for the standard prototypes exist, and lament otherwise
|
// make sure the directories for the standard prototypes exist, and lament otherwise
|
||||||
|
@ -54,6 +59,9 @@ public final class TypeManager {
|
||||||
}
|
}
|
||||||
prototypes = new HashMap ();
|
prototypes = new HashMap ();
|
||||||
zipfiles = new HashMap ();
|
zipfiles = new HashMap ();
|
||||||
|
jarfiles = new HashSet ();
|
||||||
|
URL helmajar = new URL ("file:"+app.home.getAbsolutePath()+"/lib/helma.jar");
|
||||||
|
loader = new AppClassLoader(app.getName(), new URL[] { helmajar });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,6 +119,16 @@ public final class TypeManager {
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (list[i].endsWith (".jar")) {
|
||||||
|
if (!jarfiles.contains (list[i])) {
|
||||||
|
jarfiles.add (list[i]);
|
||||||
|
File f = new File (appDir, list[i]);
|
||||||
|
try {
|
||||||
|
loader.addURL (new URL ("file:"+f.getAbsolutePath()));
|
||||||
|
} catch (MalformedURLException ignore) {}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (list[i].indexOf ('.') > -1)
|
if (list[i].indexOf ('.') > -1)
|
||||||
continue;
|
continue;
|
||||||
Prototype proto = getPrototype (list[i]);
|
Prototype proto = getPrototype (list[i]);
|
||||||
|
|
94
src/helma/main/HelmaSecurityManager.java
Normal file
94
src/helma/main/HelmaSecurityManager.java
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
// HelmaSecurityManager.java
|
||||||
|
|
||||||
|
package helma.main;
|
||||||
|
|
||||||
|
import java.security.Permission;
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import helma.framework.core.AppClassLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liberal security manager for Helma system that makes sure application code
|
||||||
|
* is not allowed to exit the VM and set a security manager.
|
||||||
|
*
|
||||||
|
* This class can be subclassed to implement actual security policies. It contains
|
||||||
|
* a utility method <code>getApplication</code> that can be used to determine
|
||||||
|
* the name of the application trying to execute the action in question, if any.
|
||||||
|
*/
|
||||||
|
public class HelmaSecurityManager extends SecurityManager {
|
||||||
|
|
||||||
|
// The set of actions forbidden to application code.
|
||||||
|
// We are pretty permissive, forbidding only System.exit()
|
||||||
|
// and setting the security manager.
|
||||||
|
private final static HashSet forbidden = new HashSet ();
|
||||||
|
static {
|
||||||
|
forbidden.add ("exitVM");
|
||||||
|
forbidden.add ("setSecurityManager");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkPermission(Permission p) {
|
||||||
|
if (p instanceof RuntimePermission) {
|
||||||
|
if (forbidden.contains (p.getName())) {
|
||||||
|
Class[] classes = getClassContext();
|
||||||
|
for (int i=0; i<classes.length; i++) {
|
||||||
|
if (classes[i].getClassLoader() instanceof AppClassLoader)
|
||||||
|
throw new SecurityException (p.getName()+" not allowed for application code");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void checkPermission(Permission p, Object context) {
|
||||||
|
}
|
||||||
|
public void checkCreateClassLoader() {}
|
||||||
|
public void checkAccess(Thread thread) {}
|
||||||
|
public void checkAccess(ThreadGroup group) {}
|
||||||
|
public void checkExit(int status) {
|
||||||
|
Class[] classes = getClassContext();
|
||||||
|
for (int i=0; i<classes.length; i++) {
|
||||||
|
if (classes[i].getClassLoader() instanceof AppClassLoader)
|
||||||
|
throw new SecurityException ("operation not allowed for application code");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void checkExec(String cmd) {}
|
||||||
|
public void checkLink(String lib) {}
|
||||||
|
public void checkRead(FileDescriptor fdesc) {}
|
||||||
|
public void checkRead(String file) {}
|
||||||
|
public void checkRead(String file, Object context) {}
|
||||||
|
public void checkWrite(FileDescriptor fdesc) {}
|
||||||
|
public void checkWrite(String file) {}
|
||||||
|
public void checkDelete(String file) {}
|
||||||
|
public void checkConnect(String host, int port) {}
|
||||||
|
public void checkConnect(String host, int port, Object context) {}
|
||||||
|
public void checkListen(int port) {}
|
||||||
|
public void checkAccept(String host, int port) {}
|
||||||
|
public void checkMulticast(InetAddress addr) {}
|
||||||
|
public void checkMulticast(InetAddress addr, byte ttl) {}
|
||||||
|
public void checkPropertiesAccess() {}
|
||||||
|
public void checkPropertyAccess(String key) {}
|
||||||
|
public boolean checkTopLevelWindow(Object window) { return true; }
|
||||||
|
public void checkPrintJobAccess() {}
|
||||||
|
public void checkSystemClipboardAccess() {}
|
||||||
|
public void checkAwtEventQueueAccess() {}
|
||||||
|
public void checkPackageAccess(String pkg) {}
|
||||||
|
public void checkPackageDefinition(String pkg) {}
|
||||||
|
public void checkSetFactory() {}
|
||||||
|
public void checkMemberAccess(Class clazz, int which) {}
|
||||||
|
public void checkSecurityAccess(String target) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility method that returns the name of the application trying
|
||||||
|
* to execute the code in question. Returns null if the current code
|
||||||
|
* does not belong to any application.
|
||||||
|
*/
|
||||||
|
protected String getApplication () {
|
||||||
|
Class[] classes = getClassContext();
|
||||||
|
for (int i=0; i<classes.length; i++) {
|
||||||
|
if (classes[i].getClassLoader() instanceof AppClassLoader)
|
||||||
|
return ((AppClassLoader) classes[i].getClassLoader()).getAppName ();
|
||||||
|
}
|
||||||
|
// no application class loader found in stack - return null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,11 +15,11 @@ import java.io.IOException;
|
||||||
* server-to-server.
|
* server-to-server.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class HopSocketFactory extends RMISocketFactory {
|
public class HelmaSocketFactory extends RMISocketFactory {
|
||||||
|
|
||||||
private InetAddressFilter filter;
|
private InetAddressFilter filter;
|
||||||
|
|
||||||
public HopSocketFactory () {
|
public HelmaSocketFactory () {
|
||||||
filter = new InetAddressFilter ();
|
filter = new InetAddressFilter ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,8 @@ import org.apache.xmlrpc.*;
|
||||||
|
|
||||||
public class Server implements IPathElement, Runnable {
|
public class Server implements IPathElement, Runnable {
|
||||||
|
|
||||||
public static final String version = "1.2pre3+ 2002/10/24";
|
public static final String version = "1.2pre3+ 2002/11/21";
|
||||||
public long starttime;
|
public final long starttime;
|
||||||
|
|
||||||
// if true we only accept RMI and XML-RPC connections from
|
// if true we only accept RMI and XML-RPC connections from
|
||||||
// explicitly listed hosts.
|
// explicitly listed hosts.
|
||||||
|
@ -141,13 +141,46 @@ import org.apache.xmlrpc.*;
|
||||||
usageError = true;
|
usageError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 ();
|
||||||
|
}
|
||||||
|
// create system properties
|
||||||
|
sysProps = new SystemProperties (propfile);
|
||||||
|
|
||||||
|
// check if there's a property setting for those ports not specified via command line
|
||||||
|
if (websrvPort == 0 && sysProps.getProperty ("webPort") != null) try {
|
||||||
|
websrvPort = Integer.parseInt (sysProps.getProperty ("webPort"));
|
||||||
|
} catch (NumberFormatException fmt) {
|
||||||
|
System.err.println ("Error parsing web server port property: "+fmt);
|
||||||
|
}
|
||||||
|
if (ajp13Port == 0 && sysProps.getProperty ("ajp13Port") != null) try {
|
||||||
|
ajp13Port = Integer.parseInt (sysProps.getProperty ("ajp13Port"));
|
||||||
|
} catch (NumberFormatException fmt) {
|
||||||
|
System.err.println ("Error parsing AJP1.3 server port property: "+fmt);
|
||||||
|
}
|
||||||
|
if (rmiPort == 0 && sysProps.getProperty ("rmiPort") != null) try {
|
||||||
|
rmiPort = Integer.parseInt (sysProps.getProperty ("rmiPort"));
|
||||||
|
} catch (NumberFormatException fmt) {
|
||||||
|
System.err.println ("Error parsing RMI server port property: "+fmt);
|
||||||
|
}
|
||||||
|
if (xmlrpcPort == 0 && sysProps.getProperty ("xmlrpcPort") != null) try {
|
||||||
|
xmlrpcPort = Integer.parseInt (sysProps.getProperty ("xmlrpcPort"));
|
||||||
|
} catch (NumberFormatException fmt) {
|
||||||
|
System.err.println ("Error parsing XML-RPC server port property: "+fmt);
|
||||||
|
}
|
||||||
|
|
||||||
// check server ports. If no port is set, issue a warning and exit.
|
// check server ports. If no port is set, issue a warning and exit.
|
||||||
if (!usageError && (websrvPort | ajp13Port | rmiPort | xmlrpcPort) == 0) {
|
if (!usageError && (websrvPort | ajp13Port | rmiPort | xmlrpcPort) == 0) {
|
||||||
System.out.println (" Error: No server port specified.");
|
System.out.println (" Error: No server port specified.");
|
||||||
usageError = true;
|
usageError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if there's a usage error, output message and exit
|
||||||
if (usageError ) {
|
if (usageError ) {
|
||||||
System.out.println ("usage: java helma.main.Server [-h dir] [-f file] [-p port] [-w port] [-x port]");
|
System.out.println ("usage: java helma.main.Server [-h dir] [-f file] [-p port] [-w port] [-x port]");
|
||||||
System.out.println (" -h dir Specify hop home directory");
|
System.out.println (" -h dir Specify hop home directory");
|
||||||
|
@ -160,7 +193,7 @@ import org.apache.xmlrpc.*;
|
||||||
System.exit (0);
|
System.exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if servers are already running on the given ports
|
// check if any of the specified server ports is in use already
|
||||||
try {
|
try {
|
||||||
if (websrvPort > 0)
|
if (websrvPort > 0)
|
||||||
checkRunning (websrvPort);
|
checkRunning (websrvPort);
|
||||||
|
@ -175,18 +208,6 @@ import org.apache.xmlrpc.*;
|
||||||
System.exit (1);
|
System.exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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 ();
|
|
||||||
}
|
|
||||||
// create system properties
|
|
||||||
sysProps = new SystemProperties (propfile);
|
|
||||||
|
|
||||||
// get hopHome from property file
|
// get hopHome from property file
|
||||||
if (homeDir == null)
|
if (homeDir == null)
|
||||||
homeDir = sysProps.getProperty ("hophome");
|
homeDir = sysProps.getProperty ("hophome");
|
||||||
|
@ -343,7 +364,7 @@ import org.apache.xmlrpc.*;
|
||||||
|
|
||||||
if (rmiPort > 0) {
|
if (rmiPort > 0) {
|
||||||
if (paranoid) {
|
if (paranoid) {
|
||||||
HopSocketFactory factory = new HopSocketFactory ();
|
HelmaSocketFactory factory = new HelmaSocketFactory ();
|
||||||
String rallow = sysProps.getProperty ("allowWeb");
|
String rallow = sysProps.getProperty ("allowWeb");
|
||||||
if (rallow != null) {
|
if (rallow != null) {
|
||||||
StringTokenizer st = new StringTokenizer (rallow, " ,;");
|
StringTokenizer st = new StringTokenizer (rallow, " ,;");
|
||||||
|
@ -370,6 +391,19 @@ import org.apache.xmlrpc.*;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the security manager.
|
||||||
|
// the default implementation is helma.main.HelmaSecurityManager.
|
||||||
|
try {
|
||||||
|
String secManClass = sysProps.getProperty ("securityManager");
|
||||||
|
if (secManClass != null) {
|
||||||
|
SecurityManager secMan = (SecurityManager) Class.forName(secManClass).newInstance ();
|
||||||
|
System.setSecurityManager (secMan);
|
||||||
|
getLogger().log ("Setting security manager to "+secManClass);
|
||||||
|
}
|
||||||
|
} catch (Exception x) {
|
||||||
|
getLogger().log ("Error setting security manager: "+x);
|
||||||
|
}
|
||||||
|
|
||||||
// start applications
|
// start applications
|
||||||
appManager.startAll ();
|
appManager.startAll ();
|
||||||
|
|
||||||
|
|
36
src/helma/main/launcher/FilteredClassLoader.java
Normal file
36
src/helma/main/launcher/FilteredClassLoader.java
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// FilteredClassLoader.java
|
||||||
|
|
||||||
|
package helma.main.launcher;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.security.PermissionCollection;
|
||||||
|
import java.security.Permissions;
|
||||||
|
import java.security.Policy;
|
||||||
|
import java.security.CodeSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassLoader that is able to exclude certain packages from loading.
|
||||||
|
*/
|
||||||
|
public class FilteredClassLoader extends URLClassLoader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a server wide class loader that doesn't see the scripting engine(s)
|
||||||
|
* embedded in helma.jar. These files should be loaded by the per-application
|
||||||
|
* class loaders so that special security policies can be applied to them and
|
||||||
|
* so that they can load classes from jar files in the app directories.
|
||||||
|
*/
|
||||||
|
public FilteredClassLoader(URL[] urls) {
|
||||||
|
super (urls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mask classes that implement the scripting engine(s) contained in helma.jar
|
||||||
|
*/
|
||||||
|
protected Class findClass (String name) throws ClassNotFoundException {
|
||||||
|
if (name != null && (name.startsWith ("helma.scripting.fesi") || name.startsWith ("FESI")))
|
||||||
|
throw new ClassNotFoundException (name);
|
||||||
|
return super.findClass (name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,8 @@ import java.net.URL;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.security.Policy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helma bootstrap class. Figures out Helma home directory, sets up class path and
|
* Helma bootstrap class. Figures out Helma home directory, sets up class path and
|
||||||
|
@ -14,44 +16,86 @@ import java.lang.reflect.Method;
|
||||||
*/
|
*/
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
|
public static final String[] jars = { "helma.jar", "jetty.jar", "crimson.jar", "xmlrpc.jar",
|
||||||
|
"village.jar", "servlet.jar", "regexp.jar", "mail.jar",
|
||||||
|
"activation.jar", "netcomponents.jar", "jimi.jar",
|
||||||
|
"apache-dom.jar", "jdom.jar"};
|
||||||
|
|
||||||
|
|
||||||
public static void main (String[] args) throws Exception {
|
public static void main (String[] args) throws Exception {
|
||||||
|
|
||||||
// try to get Helma installation directory
|
// check if home directory is set via command line arg. If not,
|
||||||
try {
|
// we'll get it from the location of the jar file this class
|
||||||
URLClassLoader apploader = (URLClassLoader) Main.class.getClassLoader();
|
// has been loaded from.
|
||||||
// (URLClassLoader) Thread.currentThread().getContextClassLoader();
|
String home = null;
|
||||||
URL homeUrl = apploader.findResource("helma/main/launcher/Main.class");
|
// first, try to get helma home dir from command line options
|
||||||
String home = homeUrl.toString().substring(4);
|
for (int i=0; i<args.length; i++) {
|
||||||
int excl = home.indexOf ("!");
|
if (args[i].equals ("-h") && i+1<args.length)
|
||||||
if (excl > -1) {
|
home = args[i+1];
|
||||||
home = home.substring(0, excl);
|
|
||||||
homeUrl = new URL (home);
|
|
||||||
File f = new File (homeUrl.getPath());
|
|
||||||
f = f.getParentFile();
|
|
||||||
System.err.println ("GOT HOME: "+f);
|
|
||||||
}
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
// unable to get Helma home dir from launcher jar
|
|
||||||
}
|
}
|
||||||
File libdir = new File ("lib");
|
URLClassLoader apploader = (URLClassLoader) ClassLoader.getSystemClassLoader();
|
||||||
File[] files = libdir.listFiles (new FilenameFilter() {
|
// try to get Helma installation directory
|
||||||
|
if (home == null) {
|
||||||
|
try {
|
||||||
|
URL homeUrl = apploader.findResource("helma/main/launcher/Main.class");
|
||||||
|
// this is a JAR URL of the form
|
||||||
|
// jar:<url>!/{entry}
|
||||||
|
// we strip away the jar: prefix and the !/{entry} suffix
|
||||||
|
// to get the original jar file URL
|
||||||
|
home = homeUrl.toString().substring(4);
|
||||||
|
int excl = home.indexOf ("!");
|
||||||
|
if (excl > -1) {
|
||||||
|
home = home.substring(0, excl);
|
||||||
|
homeUrl = new URL (home);
|
||||||
|
File f = new File (homeUrl.getPath());
|
||||||
|
home = f.getParent();
|
||||||
|
// add home dir to the command line arguments
|
||||||
|
String[] newArgs = new String [args.length+2];
|
||||||
|
newArgs[0] = "-h";
|
||||||
|
newArgs[1] = home;
|
||||||
|
System.arraycopy (args, 0, newArgs, 2, args.length);
|
||||||
|
args = newArgs;
|
||||||
|
}
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
// unable to get Helma home dir from launcher jar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// set the current working directory to the helma home dir.
|
||||||
|
// note that this is not a real cwd, which is not supported
|
||||||
|
// by java. It makes sure relative to absolute path name
|
||||||
|
// conversion is done right, so for Helma code, this should
|
||||||
|
// work.
|
||||||
|
System.setProperty ("user.dir", home);
|
||||||
|
|
||||||
|
// set up the class path
|
||||||
|
File libdir = new File (home, "lib");
|
||||||
|
ArrayList jarlist = new ArrayList ();
|
||||||
|
for (int i=0;i<jars.length;i++) {
|
||||||
|
File jar = new File (libdir, jars[i]);
|
||||||
|
if (jar.exists())
|
||||||
|
jarlist.add (new URL ("file:" + jar.getAbsolutePath()));
|
||||||
|
}
|
||||||
|
// add all jar files from the lib/ext directory
|
||||||
|
File extdir =new File (libdir, "ext");
|
||||||
|
File[] files = extdir.listFiles (new FilenameFilter() {
|
||||||
public boolean accept (File dir, String name) {
|
public boolean accept (File dir, String name) {
|
||||||
if (name.startsWith ("helma"))
|
|
||||||
return "helma.jar".equals (name);
|
|
||||||
return name.endsWith (".jar");
|
return name.endsWith (".jar");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
URL[] urls = new URL[files.length];
|
if (files != null)
|
||||||
for (int i=0; i<files.length; i++) {
|
for (int i=0;i<files.length; i++)
|
||||||
urls[i] = new URL ("file:"+files[i].getAbsolutePath());
|
jarlist.add (new URL ("file:" + files[i].getAbsolutePath()));
|
||||||
}
|
URL[] urls = new URL[jarlist.size()];
|
||||||
URLClassLoader loader = new URLClassLoader (urls);
|
jarlist.toArray (urls);
|
||||||
|
FilteredClassLoader loader = new FilteredClassLoader (urls);
|
||||||
|
// set the new class loader as context class loader
|
||||||
Thread.currentThread().setContextClassLoader (loader);
|
Thread.currentThread().setContextClassLoader (loader);
|
||||||
|
// get the main server class
|
||||||
Class clazz = loader.loadClass ("helma.main.Server");
|
Class clazz = loader.loadClass ("helma.main.Server");
|
||||||
Class[] cargs = new Class[] { args.getClass() };
|
Class[] cargs = new Class[] { args.getClass() };
|
||||||
Method main = clazz.getMethod ("main", cargs);
|
Method main = clazz.getMethod ("main", cargs);
|
||||||
Object[] nargs = new Object[] { args };
|
Object[] nargs = new Object[] { args };
|
||||||
|
// run
|
||||||
main.invoke (null, nargs);
|
main.invoke (null, nargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue