/
codebase/
codebase/area/
codebase/doc/
codebase/etc/
codebase/src/net/sourceforge/pain/data/trigger/
codebase/src/net/sourceforge/pain/logic/
codebase/src/net/sourceforge/pain/logic/affect/
codebase/src/net/sourceforge/pain/logic/event/
codebase/src/net/sourceforge/pain/logic/event/deploy/
codebase/src/net/sourceforge/pain/logic/event/guitool/
codebase/src/net/sourceforge/pain/logic/event/guitool/event/
codebase/src/net/sourceforge/pain/logic/fn/util/
codebase/src/net/sourceforge/pain/logic/trigger/
codebase/src/net/sourceforge/pain/logic/trigger/impl/
codebase/src/net/sourceforge/pain/network/console/
codebase/src/net/sourceforge/pain/network/console/telnet/
codebase/src/net/sourceforge/pain/network/guitool/
codebase/src/net/sourceforge/pain/plugin/
codebase/src/net/sourceforge/pain/plugin/command/
codebase/src/net/sourceforge/pain/plugin/reset/
codebase/src/net/sourceforge/pain/plugin/shutdown/
codebase/src/net/sourceforge/pain/plugin/social/
codebase/src/net/sourceforge/pain/util/
db/doc/javadoc/resources/
db/src/net/sourceforge/pain/util/
gui/
gui/lib/
gui/src/net/sourceforge/pain/tools/guitool/dbbrowse/
gui/src/net/sourceforge/pain/tools/guitool/dialog/
gui/src/net/sourceforge/pain/tools/guitool/menu/
gui/src/net/sourceforge/pain/tools/guitool/resources/
gui/src/net/sourceforge/pain/tools/guitool/resources/images/
gui/src/net/sourceforge/pain/tools/guitool/resources/images/explorer/
tests/
tests/src/
tests/src/net/sourceforge/pain/db/data/
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");
        }
    }
}