/
area/
classes/net/sourceforge/pain/logic/
classes/net/sourceforge/pain/logic/event/
classes/net/sourceforge/pain/logic/fn/util/
classes/net/sourceforge/pain/network/console/
classes/net/sourceforge/pain/plugin/
classes/net/sourceforge/pain/plugin/reset/
classes/net/sourceforge/pain/plugin/shutdown/
classes/net/sourceforge/pain/plugin/social/
classest/net/sourceforge/pain/db/data/
doc/
doc/paindb/resources/
src/net/sourceforge/pain/logic/
src/net/sourceforge/pain/logic/event/
src/net/sourceforge/pain/logic/fn/util/
src/net/sourceforge/pain/network/console/
src/net/sourceforge/pain/network/console/telnet/
src/net/sourceforge/pain/plugin/
src/net/sourceforge/pain/plugin/command/
src/net/sourceforge/pain/plugin/reset/
src/net/sourceforge/pain/plugin/shutdown/
src/net/sourceforge/pain/plugin/social/
src/net/sourceforge/pain/util/
tests/
tests/net/sourceforge/pain/db/data/
package net.sourceforge.pain.plugin;


import net.sourceforge.pain.*;
import net.sourceforge.pain.util.*;

import java.io.*;


public final class PluginClassLoader extends ClassLoader {

	/**
	 *  in this release every plugin should have it's own package (1pack to 1plug) inside net.sf.pain.plugins
	 *  we need this info during plugins load (to separate classloaders for different plugins using it classnames)
	 */
	public final String pluginDir;

	private Plugin plugin;
	public final PluginManager plm;
	private int number;//for debug

	protected PluginClassLoader(PluginManager plm, String pluginName) throws Exception {
		number = plm.counter++;
		Log.debug("PlugCL[" + number + "]:creating:" + pluginName);
		this.plm = plm;
		int i = pluginName.indexOf('.');
		pluginDir = pluginName.substring(0, i + 1);
		Class pluginClass = _loadClass(PluginManager.PLUGINS_HOME + pluginName);
		plugin = (Plugin) pluginClass.newInstance();
		plugin.loader = this;
		plugin.pluginName = pluginName;
		plugin.init();
	}

	public Class loadClass(String className) throws ClassNotFoundException {
		if (!className.startsWith(PluginManager.PLUGINS_HOME) || className.indexOf('.', PluginManager.PLUGINS_HOME_LENGTH ) == -1) {
			return Class.forName(className);
		}
		// this class is from plugins package->check if this package is for this classloader
		if (!className.substring(PluginManager.PLUGINS_HOME_LENGTH).startsWith(pluginDir)) {
			// this is class with different class loader
			return plm.loadClassByPluginClassloader(plugin.pluginName, className);
		}
		return _loadClass(className);
	}

	private Class _loadClass(String className) throws ClassNotFoundException {
		Log.debug("PlugCL[" + number + "] Classloader: _loadClass:" + className);
		Class c = findLoadedClass(className);
		if (c == null) {
			c = defineClassFromFile(className);
		} else {
			Log.debug("[" + number + "]PLM Classloader: _loadClass: found loaded:" + className);
		}
		return c;
	}

	public Plugin getPlugin() {
		return plugin;
	}

	protected Class defineClassFromFile(String className) throws ClassNotFoundException {
		Log.debug("PlugCL[" + number + "] Classloader: defineClass:" + className);
		try {
			byte[] data = Core.getFileData(plm.dirPath + "/" + className.replace('.', '/') + ".class");
			return super.defineClass(className, data, 0, data.length);
		} catch (IOException e) {
			Log.error(e.getMessage(), e);
			throw new ClassNotFoundException("Class File Not Found:" + plm.dirPath + "/" + className + ".class");
		}
	}

}