* Run Application.init() in a fresh thread to shield it against class loaders
and rhino contexts that may be associated with the calling thread. Fixes bug 613 <http://helma.org/bugs/show_bug.cgi?id=613>
This commit is contained in:
parent
007f61b324
commit
30eb6663bc
1 changed files with 149 additions and 110 deletions
|
@ -303,9 +303,9 @@ public final class Application implements 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 synchronized void init()
|
public void init()
|
||||||
throws DatabaseException, IllegalAccessException,
|
throws DatabaseException, IllegalAccessException, InstantiationException,
|
||||||
InstantiationException, ClassNotFoundException {
|
ClassNotFoundException, InterruptedException {
|
||||||
init(null);
|
init(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,125 +314,164 @@ public final class Application implements Runnable {
|
||||||
*
|
*
|
||||||
* @param ignoreDirs comma separated list of directory names to ignore
|
* @param ignoreDirs comma separated list of directory names to ignore
|
||||||
*/
|
*/
|
||||||
public synchronized void init(String ignoreDirs)
|
public void init(final String ignoreDirs)
|
||||||
throws DatabaseException, IllegalAccessException,
|
throws DatabaseException, IllegalAccessException, InstantiationException,
|
||||||
InstantiationException, ClassNotFoundException {
|
ClassNotFoundException, InterruptedException {
|
||||||
|
|
||||||
running = true;
|
Initializer i = new Initializer(ignoreDirs);
|
||||||
|
i.start();
|
||||||
|
i.join();
|
||||||
|
if (i.exception != null) {
|
||||||
|
if (i.exception instanceof DatabaseException)
|
||||||
|
throw (DatabaseException) i.exception;
|
||||||
|
if (i.exception instanceof IllegalAccessException)
|
||||||
|
throw (IllegalAccessException) i.exception;
|
||||||
|
if (i.exception instanceof InstantiationException)
|
||||||
|
throw (InstantiationException) i.exception;
|
||||||
|
if (i.exception instanceof ClassNotFoundException)
|
||||||
|
throw (ClassNotFoundException) i.exception;
|
||||||
|
throw new RuntimeException(i.exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create and init type mananger
|
// We need to call initialize in a fresh thread because the calling thread could
|
||||||
typemgr = new TypeManager(this, ignoreDirs);
|
// already be associated with a rhino context, for example when starting from the
|
||||||
// set the context classloader. Note that this must be done before
|
// manage application.
|
||||||
// using the logging framework so that a new LogFactory gets created
|
class Initializer extends Thread {
|
||||||
// for this app.
|
Exception exception = null;
|
||||||
Thread.currentThread().setContextClassLoader(typemgr.getClassLoader());
|
String ignoreDirs;
|
||||||
try {
|
|
||||||
typemgr.createPrototypes();
|
Initializer(String dirs) {
|
||||||
} catch (Exception x) {
|
super("INIT-" + name);
|
||||||
logError("Error creating prototypes", x);
|
ignoreDirs = dirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Server.getServer() != null) {
|
public void run() {
|
||||||
Vector extensions = Server.getServer().getExtensions();
|
try {
|
||||||
|
synchronized (Application.this) {
|
||||||
|
initInternal();
|
||||||
|
}
|
||||||
|
} catch (Exception x) {
|
||||||
|
exception = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < extensions.size(); i++) {
|
private void initInternal()
|
||||||
HelmaExtension ext = (HelmaExtension) extensions.get(i);
|
throws DatabaseException, IllegalAccessException,
|
||||||
|
InstantiationException, ClassNotFoundException {
|
||||||
|
running = true;
|
||||||
|
// create and init type mananger
|
||||||
|
typemgr = new TypeManager(Application.this, ignoreDirs);
|
||||||
|
// set the context classloader. Note that this must be done before
|
||||||
|
// using the logging framework so that a new LogFactory gets created
|
||||||
|
// for this app.
|
||||||
|
Thread.currentThread().setContextClassLoader(typemgr.getClassLoader());
|
||||||
|
try {
|
||||||
|
typemgr.createPrototypes();
|
||||||
|
} catch (Exception x) {
|
||||||
|
logError("Error creating prototypes", x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Server.getServer() != null) {
|
||||||
|
Vector extensions = Server.getServer().getExtensions();
|
||||||
|
|
||||||
|
for (int i = 0; i < extensions.size(); i++) {
|
||||||
|
HelmaExtension ext = (HelmaExtension) extensions.get(i);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ext.applicationStarted(Application.this);
|
||||||
|
} catch (ConfigurationException e) {
|
||||||
|
logEvent("couldn't init extension " + ext.getName() + ": " +
|
||||||
|
e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create and init evaluator/thread lists
|
||||||
|
freeThreads = new Stack();
|
||||||
|
allThreads = new Vector();
|
||||||
|
|
||||||
|
// preallocate minThreads request evaluators
|
||||||
|
int minThreads = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
minThreads = Integer.parseInt(props.getProperty("minThreads"));
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
// not parsable as number, keep 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minThreads > 0) {
|
||||||
|
logEvent("Starting "+minThreads+" evaluator(s) for " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < minThreads; i++) {
|
||||||
|
RequestEvaluator ev = new RequestEvaluator(Application.this);
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
ev.initScriptingEngine();
|
||||||
|
}
|
||||||
|
freeThreads.push(ev);
|
||||||
|
allThreads.addElement(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
activeRequests = new Hashtable();
|
||||||
|
activeCronJobs = new Hashtable();
|
||||||
|
customCronJobs = new Hashtable();
|
||||||
|
|
||||||
|
// create the skin manager
|
||||||
|
skinmgr = new SkinManager(Application.this);
|
||||||
|
|
||||||
|
// read in root id, root prototype, user prototype
|
||||||
|
rootId = props.getProperty("rootid", "0");
|
||||||
|
String rootPrototype = props.getProperty("rootprototype", "root");
|
||||||
|
String userPrototype = props.getProperty("userprototype", "user");
|
||||||
|
|
||||||
|
rootMapping = getDbMapping(rootPrototype);
|
||||||
|
if (rootMapping == null)
|
||||||
|
throw new RuntimeException("rootPrototype does not exist: " + rootPrototype);
|
||||||
|
userMapping = getDbMapping(userPrototype);
|
||||||
|
if (userMapping == null)
|
||||||
|
throw new RuntimeException("userPrototype does not exist: " + userPrototype);
|
||||||
|
|
||||||
|
// The whole user/userroot handling is basically old
|
||||||
|
// ugly obsolete crap. Don't bother.
|
||||||
|
ResourceProperties p = new ResourceProperties();
|
||||||
|
String usernameField = (userMapping != null) ? userMapping.getNameField() : null;
|
||||||
|
|
||||||
|
if (usernameField == null) {
|
||||||
|
usernameField = "name";
|
||||||
|
}
|
||||||
|
|
||||||
|
p.put("_children", "collection(" + userPrototype + ")");
|
||||||
|
p.put("_children.accessname", usernameField);
|
||||||
|
userRootMapping = new DbMapping(Application.this, "__userroot__", p);
|
||||||
|
userRootMapping.update();
|
||||||
|
|
||||||
|
// create the node manager
|
||||||
|
nmgr = new NodeManager(Application.this);
|
||||||
|
nmgr.init(dbDir.getAbsoluteFile(), props);
|
||||||
|
|
||||||
|
// create and init session manager
|
||||||
|
String sessionMgrImpl = props.getProperty("sessionManagerImpl",
|
||||||
|
"helma.framework.core.SessionManager");
|
||||||
|
sessionMgr = (SessionManager) Class.forName(sessionMgrImpl).newInstance();
|
||||||
|
logEvent("Using session manager class " + sessionMgrImpl);
|
||||||
|
sessionMgr.init(Application.this);
|
||||||
|
|
||||||
|
// read the sessions if wanted
|
||||||
|
if ("true".equalsIgnoreCase(getProperty("persistentSessions"))) {
|
||||||
|
RequestEvaluator ev = getEvaluator();
|
||||||
try {
|
try {
|
||||||
ext.applicationStarted(this);
|
ev.initScriptingEngine();
|
||||||
} catch (ConfigurationException e) {
|
sessionMgr.loadSessionData(null, ev.scriptingEngine);
|
||||||
logEvent("couldn't init extension " + ext.getName() + ": " +
|
} finally {
|
||||||
e.toString());
|
releaseEvaluator(ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create and init evaluator/thread lists
|
|
||||||
freeThreads = new Stack();
|
|
||||||
allThreads = new Vector();
|
|
||||||
|
|
||||||
// preallocate minThreads request evaluators
|
|
||||||
int minThreads = 0;
|
|
||||||
|
|
||||||
try {
|
|
||||||
minThreads = Integer.parseInt(props.getProperty("minThreads"));
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
// not parsable as number, keep 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if (minThreads > 0) {
|
|
||||||
logEvent("Starting "+minThreads+" evaluator(s) for " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < minThreads; i++) {
|
|
||||||
RequestEvaluator ev = new RequestEvaluator(this);
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
ev.initScriptingEngine();
|
|
||||||
}
|
|
||||||
freeThreads.push(ev);
|
|
||||||
allThreads.addElement(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
activeRequests = new Hashtable();
|
|
||||||
activeCronJobs = new Hashtable();
|
|
||||||
customCronJobs = new Hashtable();
|
|
||||||
|
|
||||||
// create the skin manager
|
|
||||||
skinmgr = new SkinManager(this);
|
|
||||||
|
|
||||||
// read in root id, root prototype, user prototype
|
|
||||||
rootId = props.getProperty("rootid", "0");
|
|
||||||
String rootPrototype = props.getProperty("rootprototype", "root");
|
|
||||||
String userPrototype = props.getProperty("userprototype", "user");
|
|
||||||
|
|
||||||
rootMapping = getDbMapping(rootPrototype);
|
|
||||||
if (rootMapping == null)
|
|
||||||
throw new RuntimeException("rootPrototype does not exist: " + rootPrototype);
|
|
||||||
userMapping = getDbMapping(userPrototype);
|
|
||||||
if (userMapping == null)
|
|
||||||
throw new RuntimeException("userPrototype does not exist: " + userPrototype);
|
|
||||||
|
|
||||||
// The whole user/userroot handling is basically old
|
|
||||||
// ugly obsolete crap. Don't bother.
|
|
||||||
ResourceProperties p = new ResourceProperties();
|
|
||||||
String usernameField = (userMapping != null) ? userMapping.getNameField() : null;
|
|
||||||
|
|
||||||
if (usernameField == null) {
|
|
||||||
usernameField = "name";
|
|
||||||
}
|
|
||||||
|
|
||||||
p.put("_children", "collection(" + userPrototype + ")");
|
|
||||||
p.put("_children.accessname", usernameField);
|
|
||||||
userRootMapping = new DbMapping(this, "__userroot__", p);
|
|
||||||
userRootMapping.update();
|
|
||||||
|
|
||||||
// create the node manager
|
|
||||||
nmgr = new NodeManager(this);
|
|
||||||
nmgr.init(dbDir.getAbsoluteFile(), props);
|
|
||||||
|
|
||||||
// create and init session manager
|
|
||||||
String sessionMgrImpl = props.getProperty("sessionManagerImpl",
|
|
||||||
"helma.framework.core.SessionManager");
|
|
||||||
sessionMgr = (SessionManager) Class.forName(sessionMgrImpl).newInstance();
|
|
||||||
logEvent("Using session manager class " + sessionMgrImpl);
|
|
||||||
sessionMgr.init(this);
|
|
||||||
|
|
||||||
// read the sessions if wanted
|
|
||||||
if ("true".equalsIgnoreCase(getProperty("persistentSessions"))) {
|
|
||||||
RequestEvaluator ev = getEvaluator();
|
|
||||||
try {
|
|
||||||
ev.initScriptingEngine();
|
|
||||||
sessionMgr.loadSessionData(null, ev.scriptingEngine);
|
|
||||||
} finally {
|
|
||||||
releaseEvaluator(ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset the classloader to the parent/system/server classloader.
|
|
||||||
Thread.currentThread().setContextClassLoader(typemgr.getClassLoader().getParent());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create and start scheduler and cleanup thread
|
* Create and start scheduler and cleanup thread
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue