package net.sourceforge.pain;
import net.sourceforge.pain.plugin.*;
import net.sourceforge.pain.util.*;
import java.io.*;
import java.util.*;
public class LogicLoadingManager {
private static final String EVENTS_PACKAGE = "net.sourceforge.pain.logic.event.";
private static int counter = 0;// for debug use
/**
* path where to look for logic class files
*/
protected String dirPath;
/**
* classloaders by classname
*/
private LogicClassLoader loader = new LogicClassLoader();
private Set reloadListeners = new HashSet();
protected LogicLoadingManager(String dirPath) {
this.dirPath = dirPath;
}
public synchronized Class provideClass(String className) throws ClassNotFoundException {
Class c = loader._findLoadedClass(className);
if (c != null) {
Log.debug("findLoadedClass works!:" + className);
return c;
}
// net.sourceforge.pain.logic.Event is not reloadable system class!
if (!className.startsWith("net.sourceforge.pain.logic.") || className.indexOf(".", 27) == -1) {
if (isPluginImpl(className)) {
Log.debug("Asking plugin from LOGIC LOADER:" + className);
return Core.getPluginManager().loadClassByPluginClassloader(null, className);
}
try {
c = Class.forName(className);
} catch (LinkageError error) {
if (error instanceof NoClassDefFoundError && error.getMessage().indexOf("wrong name:") > 0) {
// case insensitive filesystem -> we will hide this errors
} else {
// this will not stop server but will panic!
Log.error("PANIC!!!", error);
}
throw new ClassNotFoundException("Error during systen class loading!", error);
}
Log.debug("findSystemClass works!:" + className);
return c;
}
Log.debug("LLM:asking logic class:" + className);
c = loader.defineClassFromFile(className);
return c;
}
private static boolean isPluginImpl(String className) {
return (className.startsWith(PluginManager.PLUGINS_HOME)
&& className.lastIndexOf('.') > PluginManager.PLUGINS_HOME_LENGTH);
}
public synchronized void reload() {
for (Iterator iterator = reloadListeners.iterator(); iterator.hasNext();) {
LogicReloadListener logicReloadListener = (LogicReloadListener) iterator.next();
logicReloadListener.onLogicReloading();
}
loader = new LogicClassLoader();
System.gc();
}
public void addLogicReloadListener(LogicReloadListener l) {
reloadListeners.add(l);
}
public void removeReloadLogicListener(LogicReloadListener l) {
reloadListeners.remove(l);
}
public ClassLoader getActiveClassLoader() {
return loader;
}
public Class provideEventClass(String eventClassSuffix) throws ClassNotFoundException {
return provideClass(EVENTS_PACKAGE + eventClassSuffix);
}
public class LogicClassLoader extends ClassLoader {
int number = counter;
protected LogicClassLoader() {
}
public synchronized Class loadClass(String className) throws ClassNotFoundException {
Log.debug("LOGIC LOADER[" + number + "]: ask load:" + className);
return provideClass(className);
}
protected Class defineClassFromFile(String className) throws ClassNotFoundException {
try {
byte[] data = Core.getFileData(dirPath + "/" + className.replace('.', '/') + ".class");
return super.defineClass(className, data, 0, data.length);
} catch (IOException e) {
Log.warn("Can't load class file! " + e.getMessage());
throw new ClassNotFoundException("Class File Not Found:" + dirPath + "/" + className + ".class");
}
}
protected Class _findLoadedClass(String className) {
return super.findLoadedClass(className);
}
protected void finalize() {
Log.debug("LOGIC LOADER[" + number + "]:finalizing");
}
}
}