/*******************************************************************************
 * Copyright (c) 2005, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.osgi.baseadaptor.loader;

import java.io.*;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.*;
import org.eclipse.osgi.baseadaptor.BaseData;
import org.eclipse.osgi.baseadaptor.bundlefile.*;
import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingStatsHook;
import org.eclipse.osgi.framework.adaptor.BundleData;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.internal.baseadaptor.AdaptorMsg;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkEvent;

/**
 * A helper class for <code>BaseClassLoader</code> implementations.  This class will keep track of 
 * <code>ClasspathEntry</code> objects for the host bundle and any attached fragment bundles.  This 
 * class takes care of seaching the <code>ClasspathEntry</code> objects for a base class loader
 * implementation.  Additional behavior may be added to a classpath manager by configuring 
 * <code>ClassLoadingHook</code> and <code>ClassLoadingStatsHook</code>.
 * @see BaseClassLoader
 * @see ClassLoadingHook
 * @see ClassLoadingStatsHook
 * @since 3.2
 */
public class ClasspathManager {
	private static final FragmentClasspath[] emptyFragments = new FragmentClasspath[0];

	private BaseData data;
	private String[] classpath;
	private ClasspathEntry[] entries;
	private BaseClassLoader classloader;
	private FragmentClasspath[] fragments = emptyFragments;
	// a colloction of String[2], each element is {"libname", "libpath"}
	private Collection loadedLibraries = null;

	/**
	 * Constructs a classpath manager for the given host base data, classpath and base class loader
	 * @param data the host base data for this classpath manager
	 * @param classpath the host classpath for this classpath manager
	 * @param classloader the BaseClassLoader for this classpath manager
	 */
	public ClasspathManager(BaseData data, String[] classpath, BaseClassLoader classloader) {
		this.data = data;
		this.classpath = classpath;
		this.classloader = classloader;
	}

	/**
	 * initializes this classpath manager.  This must be called after all existing fragments have been
	 * attached and before any resources/classes are loaded using this classpath manager.
	 * <p>
	 * After the classpath manager is initialized all configured class loading hooks 
	 * {@link ClassLoadingHook#initializedClassLoader(BaseClassLoader, BaseData)} methods are called.
	 * </p>
	 */
	public void initialize() {
		entries = buildClasspath(classpath, this, data, classloader.getDomain());
		ClassLoadingHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingHooks();
		for (int i = 0; i < hooks.length; i++)
			hooks[i].initializedClassLoader(classloader, data);
	}

	/**
	 * Closes all the classpath entry resources for this classpath manager.
	 *
	 */
	public void close() {
		if (entries != null) {
			for (int i = 0; i < entries.length; i++) {
				if (entries[i] != null) {
					try {
						entries[i].getBundleFile().close();
					} catch (IOException e) {
						data.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, data.getBundle(), e);
					}
				}
			}
		}
		for (int i = 0; i < fragments.length; i++)
			fragments[i].close();
	}

	/**
	 * Attaches the specified sourcedata, sourcedomain and sourceclasspath to this classpath manager
	 * @param sourcedata the source fragment BundleData that should be attached.
	 * @param sourcedomain the source fragment domain that should be attached.
	 * @param sourceclasspath the source fragment classpath that should be attached.
	 */
	public void attachFragment(BundleData sourcedata, ProtectionDomain sourcedomain, String[] sourceclasspath) {
		try {
			sourcedata.open(); /* make sure the BundleData is open */
		} catch (IOException e) {
			((BaseData) sourcedata).getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, ((BaseData) sourcedata).getBundle(), e);
		}
		ClasspathEntry[] fragEntries = buildClasspath(sourceclasspath, this, (BaseData) sourcedata, sourcedomain);
		FragmentClasspath fragClasspath = new FragmentClasspath((BaseData) sourcedata, fragEntries, sourcedomain);
		insertFragment(fragClasspath);
	}

	private synchronized void insertFragment(FragmentClasspath fragClasspath) {
		FragmentClasspath[] newFragments = new FragmentClasspath[fragments.length + 1];
		// Find a place in the fragment list to insert this fragment.
		long fragID = fragClasspath.getBundleData().getBundleID();
		int insert = 0;
		for (int i = 0; i < fragments.length; i++) {
			long otherID = fragments[i].getBundleData().getBundleID();
			if (insert == 0 && fragID < otherID) {
				newFragments[i] = fragClasspath;
				insert = 1;
			}
			newFragments[i + insert] = fragments[i];
		}
		// This fragment has the highest ID; put it at the end of the list.
		if (insert == 0)
			newFragments[fragments.length] = fragClasspath;
		fragments = newFragments;
	}

	private static ClasspathEntry[] buildClasspath(String[] cp, ClasspathManager hostloader, BaseData sourcedata, ProtectionDomain sourcedomain) {
		ArrayList result = new ArrayList(cp.length);
		// add the regular classpath entries.
		for (int i = 0; i < cp.length; i++)
			findClassPathEntry(result, cp[i], hostloader, sourcedata, sourcedomain);
		return (ClasspathEntry[]) result.toArray(new ClasspathEntry[result.size()]);
	}

	/**
	 * Finds all the ClasspathEntry objects for the requested classpath.  This method will first call all
	 * the configured class loading hooks {@link ClassLoadingHook#addClassPathEntry(ArrayList, String, ClasspathManager, BaseData, ProtectionDomain)}
	 * methods.  This allows class loading hooks to add additional ClasspathEntry objects to the result for the 
	 * requested classpath.  Then the local host classpath entries and attached fragment classpath entries are
	 * searched.
	 * @param result a list of ClasspathEntry objects.  This list is used to add new ClasspathEntry objects to.
	 * @param cp the requested classpath.
	 * @param hostloader the host classpath manager for the classpath
	 * @param sourcedata the source EquionoxData to search for the classpath
	 * @param sourcedomain the source domain to used by the new ClasspathEntry
	 */
	public static void findClassPathEntry(ArrayList result, String cp, ClasspathManager hostloader, BaseData sourcedata, ProtectionDomain sourcedomain) {
		// look in classpath manager hooks first
		ClassLoadingHook[] loaderHooks = sourcedata.getAdaptor().getHookRegistry().getClassLoadingHooks();
		boolean hookAdded = false;
		for (int i = 0; i < loaderHooks.length; i++)
			hookAdded |= loaderHooks[i].addClassPathEntry(result, cp, hostloader, sourcedata, sourcedomain);
		if (!addClassPathEntry(result, cp, hostloader, sourcedata, sourcedomain) && !hookAdded) {
			BundleException be = new BundleException(NLS.bind(AdaptorMsg.BUNDLE_CLASSPATH_ENTRY_NOT_FOUND_EXCEPTION, cp, sourcedata.getLocation()));
			sourcedata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.INFO, sourcedata.getBundle(), be);
		}
	}

	/**
	 * Adds a ClasspathEntry for the requested classpath to the result.  The local host classpath entries
	 * are searched first and then attached fragments classpath entries are searched.  The search stops once the first
	 * classpath entry is found.
	 * @param result a list of ClasspathEntry objects.  This list is used to add new ClasspathEntry objects to.
	 * @param cp the requested classpath.
	 * @param hostloader the host classpath manager for the classpath
	 * @param sourcedata the source EquionoxData to search for the classpath
	 * @param sourcedomain the source domain to used by the new ClasspathEntry
	 * @return true if a ClasspathEntry was added to the result
	 */
	public static boolean addClassPathEntry(ArrayList result, String cp, ClasspathManager hostloader, BaseData sourcedata, ProtectionDomain sourcedomain) {
		if (cp.equals(".")) { //$NON-NLS-1$
			result.add(hostloader.createClassPathEntry(sourcedata.getBundleFile(), sourcedomain));
			return true;
		}
		Object element = hostloader.getClasspath(cp, sourcedata, sourcedomain);
		if (element != null) {
			result.add(element);
			return true;
		}
		// need to check in fragments for the classpath entry.
		// only check for fragments if the data is the host's data.
		if (hostloader.data == sourcedata)
			for (int i = 0; i < hostloader.fragments.length; i++) {
				FragmentClasspath fragCP = hostloader.fragments[i];
				element = hostloader.getClasspath(cp, fragCP.getBundleData(), fragCP.getDomain());
				if (element != null) {
					result.add(element);
					return true;
				}
			}
		return false;
	}

	/**
	 * Creates a new ClasspathEntry object for the requested classpath if the source exists.
	 * @param cp the requested classpath.
	 * @param sourcedata the source EquionoxData to search for the classpath
	 * @param sourcedomain the source domain to used by the new ClasspathEntry
	 * @return a new ClasspathEntry for the requested classpath or null if the source does not exist.
	 */
	public ClasspathEntry getClasspath(String cp, BaseData sourcedata, ProtectionDomain sourcedomain) {
		BundleFile bundlefile = null;
		File file;
		BundleEntry cpEntry = sourcedata.getBundleFile().getEntry(cp);
		// check for internal library directories in a bundle jar file
		if (cpEntry != null && cpEntry.getName().endsWith("/")) //$NON-NLS-1$
			bundlefile = createBundleFile(cp, sourcedata);
		// check for internal library jars
		else if ((file = sourcedata.getBundleFile().getFile(cp, false)) != null)
			bundlefile = createBundleFile(file, sourcedata);
		if (bundlefile != null)
			return createClassPathEntry(bundlefile, sourcedomain);
		return null;
	}

	/**
	 * Uses the requested classpath as an absolute path to locate a source for a new ClasspathEntry.
	 * @param cp the requested classpath
	 * @param sourcedata the source EquionoxData to search for the classpath
	 * @param sourcedomain the source domain to used by the new ClasspathEntry
	 * @return a classpath entry which uses an absolut path as a source
	 */
	public ClasspathEntry getExternalClassPath(String cp, BaseData sourcedata, ProtectionDomain sourcedomain) {
		File file = new File(cp);
		if (!file.isAbsolute())
			return null;
		BundleFile bundlefile = createBundleFile(file, sourcedata);
		if (bundlefile != null)
			return createClassPathEntry(bundlefile, sourcedomain);
		return null;
	}

	private static BundleFile createBundleFile(Object content, BaseData sourcedata) {
		if (content == null || (content instanceof File && !((File) content).exists()))
			return null;
		try {
			return sourcedata.getAdaptor().createBundleFile(content, sourcedata);
		} catch (IOException e) {
			sourcedata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, sourcedata.getBundle(), e);
		}
		return null;
	}

	private ClasspathEntry createClassPathEntry(BundleFile bundlefile, ProtectionDomain cpDomain) {
		return classloader.createClassPathEntry(bundlefile, cpDomain);
	}

	/**
	 * Finds a local resource by searching the ClasspathEntry objects of the classpath manager.
	 * This method will first call all the configured class loading stats hooks 
	 * {@link ClassLoadingStatsHook#preFindLocalResource(String, ClasspathManager)} methods.  Then it 
	 * will search for the resource.  Finally it will call all the configured class loading stats hooks
	 * {@link ClassLoadingStatsHook#postFindLocalResource(String, URL, ClasspathManager)} methods.
	 * @param resource the requested resource name.
	 * @return the requested resource URL or null if the resource does not exist
	 */
	public URL findLocalResource(String resource) {
		ClassLoadingStatsHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingStatsHooks();
		for (int i = 0; i < hooks.length; i++)
			hooks[i].preFindLocalResource(resource, this);
		URL result = null;
		try {
			result = findLocalResourceImpl(resource);
			return result;
		} finally {
			for (int i = 0; i < hooks.length; i++)
				hooks[i].postFindLocalResource(resource, result, this);
		}
	}

	private URL findLocalResourceImpl(String resource) {
		URL result = null;
		for (int i = 0; i < entries.length; i++) {
			if (entries[i] != null) {
				result = findResourceImpl(resource, entries[i].getBundleFile());
				if (result != null)
					return result;
			}
		}
		// look in fragments
		for (int i = 0; i < fragments.length; i++) {
			ClasspathEntry[] fragEntries = fragments[i].getEntries();
			for (int j = 0; j < fragEntries.length; j++) {
				result = findResourceImpl(resource, fragEntries[j].getBundleFile());
				if (result != null)
					return result;
			}
		}
		return null;
	}

	/**
	 * Finds the local resources by searching the ClasspathEntry objects of the classpath manager.
	 * @param resource the requested resource name.
	 * @return an enumeration of the the requested resources or null if the resources do not exist
	 */
	public Enumeration findLocalResources(String resource) {
		Vector resources = new Vector(6); // use a Vector instead of ArrayList because we need an enumeration
		for (int i = 0; i < entries.length; i++) {
			if (entries[i] != null) {
				URL url = findResourceImpl(resource, entries[i].getBundleFile(), resources.size());
				if (url != null)
					resources.addElement(url);
			}
		}
		// look in fragments
		for (int i = 0; i < fragments.length; i++) {
			ClasspathEntry[] fragEntries = fragments[i].getEntries();
			for (int j = 0; j < fragEntries.length; j++) {
				URL url = findResourceImpl(resource, fragEntries[j].getBundleFile(), resources.size());
				if (url != null)
					resources.addElement(url);
			}
		}
		if (resources.size() > 0)
			return resources.elements();
		return null;
	}

	private URL findResourceImpl(String name, BundleFile bundlefile) {
		return findResourceImpl(name, bundlefile, 0);
	}

	private URL findResourceImpl(String name, BundleFile bundlefile, int index) {
		return bundlefile.getResourceURL(name, data.getBundleID(), index);
	}

	/**
	 * Finds a local entry by searching the ClasspathEntry objects of the classpath manager.
	 * @param path the requested entry path.
	 * @return the requested entry or null if the entry does not exist
	 */
	public BundleEntry findLocalEntry(String path) {
		BundleEntry result = null;
		for (int i = 0; i < entries.length; i++) {
			if (entries[i] != null) {
				result = findEntryImpl(path, entries[i].getBundleFile());
				if (result != null)
					return result;
			}
		}
		// look in fragments
		for (int i = 0; i < fragments.length; i++) {
			ClasspathEntry[] fragEntries = fragments[i].getEntries();
			for (int j = 0; j < fragEntries.length; j++) {
				result = findEntryImpl(path, fragEntries[j].getBundleFile());
				if (result != null)
					return result;
			}
		}
		return null;
	}

	/**
	 * Finds the local entries by searching the ClasspathEntry objects of the classpath manager.
	 * @param path the requested entry path.
	 * @return an enumeration of the the requested entries or null if the entries do not exist
	 */
	public Enumeration findLocalEntries(String path) {
		Vector objects = new Vector(6); // use a Vector instead of ArrayList because we need an enumeration
		for (int i = 0; i < entries.length; i++) {
			if (entries[i] != null) {
				BundleEntry result = findEntryImpl(path, entries[i].getBundleFile());
				if (result != null)
					objects.addElement(result);
			}
		}
		// look in fragments
		for (int i = 0; i < fragments.length; i++) {
			ClasspathEntry[] fragEntries = fragments[i].getEntries();
			for (int j = 0; j < fragEntries.length; j++) {
				BundleEntry result = findEntryImpl(path, fragEntries[j].getBundleFile());
				if (result != null)
					objects.addElement(result);
			}
		}
		if (objects.size() > 0)
			return objects.elements();
		return null;
	}

	private BundleEntry findEntryImpl(String path, BundleFile bundleFile) {
		return bundleFile.getEntry(path);
	}

	/**
	 * Finds a local class by searching the ClasspathEntry objects of the classpath manager.
	 * This method will first call all the configured class loading stats hooks 
	 * {@link ClassLoadingStatsHook#preFindLocalClass(String, ClasspathManager)} methods.  Then it 
	 * will search for the class.  If a class is found then all configured class loading hooks
	 * {@link ClassLoadingHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
	 * methods will be called.  The class is then defined; if successfully then all configured class loading 
	 * stats hooks {@link ClassLoadingStatsHook#recordClassDefine(String, Class, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
	 * methods are called.  Finally all the configured class loading stats hooks
	 * {@link ClassLoadingStatsHook#postFindLocalClass(String, Class, ClasspathManager)} methods are called.
	 * @param classname the requested class name.
	 * @return the requested class
	 * @throws ClassNotFoundException if the class does not exist
	 */
	public Class findLocalClass(String classname) throws ClassNotFoundException {
		Class result = null;
		ClassLoadingStatsHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingStatsHooks();
		try {
			for (int i = 0; i < hooks.length; i++)
				hooks[i].preFindLocalClass(classname, this);
			result = findLocalClassImpl(classname, hooks);
			return result;
		} finally {
			for (int i = 0; i < hooks.length; i++)
				hooks[i].postFindLocalClass(classname, result, this);
		}
	}

	private Class findLocalClassImpl(String classname, ClassLoadingStatsHook[] hooks) throws ClassNotFoundException {
		// must call findLoadedClass here even if it was called earlier,
		// the findLoadedClass and defineClass calls must be atomic
		synchronized (classloader) {
			Class result = classloader.publicFindLoaded(classname);
			if (result != null)
				return result;
			for (int i = 0; i < entries.length; i++) {
				if (entries[i] != null) {
					result = findClassImpl(classname, entries[i], hooks);
					if (result != null)
						return result;
				}
			}
			// look in fragments.
			for (int i = 0; i < fragments.length; i++) {
				ClasspathEntry[] fragEntries = fragments[i].getEntries();
				for (int j = 0; j < fragEntries.length; j++) {
					result = findClassImpl(classname, fragEntries[j], hooks);
					if (result != null)
						return result;
				}
			}
		}
		throw new ClassNotFoundException(classname);
	}

	private Class findClassImpl(String name, ClasspathEntry classpathEntry, ClassLoadingStatsHook[] hooks) {
		if (Debug.DEBUG && Debug.DEBUG_LOADER)
			Debug.println("BundleClassLoader[" + data + "].findClass(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
		String filename = name.replace('.', '/').concat(".class"); //$NON-NLS-1$
		BundleEntry entry = classpathEntry.getBundleFile().getEntry(filename);
		if (entry == null)
			return null;

		byte[] classbytes;
		try {
			classbytes = entry.getBytes();
		} catch (IOException e) {
			if (Debug.DEBUG && Debug.DEBUG_LOADER)
				Debug.println("  IOException reading " + filename + " from " + data); //$NON-NLS-1$ //$NON-NLS-2$
			return null;
		}

		if (Debug.DEBUG && Debug.DEBUG_LOADER) {
			Debug.println("  read " + classbytes.length + " bytes from " + filename); //$NON-NLS-1$ //$NON-NLS-2$
			Debug.println("  defining class " + name); //$NON-NLS-1$
		}

		try {
			return defineClass(name, classbytes, classpathEntry, entry, hooks);
		} catch (Error e) {
			if (Debug.DEBUG && Debug.DEBUG_LOADER)
				Debug.println("  error defining class " + name); //$NON-NLS-1$
			throw e;
		}
	}

	/**
	 * Defines the specified class.  This method will first call all the configured class loading hooks 
	 * {@link ClassLoadingHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)} 
	 * methods.  Then it will call the {@link BaseClassLoader#defineClass(String, byte[], ClasspathEntry, BundleEntry)}
	 * method to define the class. After that, the class loading stat hooks are called to announce the class
	 * definition.
	 * @param name the name of the class to define
	 * @param classbytes the class bytes
	 * @param classpathEntry the classpath entry used to load the class bytes
	 * @param entry the BundleEntry used to load the class bytes
	 * @param statsHooks the class loading stat hooks
	 * @return the defined class
	 */
	private Class defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClassLoadingStatsHook[] statsHooks) {
		ClassLoadingHook[] hooks = data.getAdaptor().getHookRegistry().getClassLoadingHooks();
		byte[] modifiedBytes = classbytes;
		for (int i = 0; i < hooks.length; i++) {
			modifiedBytes = hooks[i].processClass(name, classbytes, classpathEntry, entry, this);
			if (modifiedBytes != null)
				classbytes = modifiedBytes;
		}

		Class result = classloader.defineClass(name, classbytes, classpathEntry, entry);

		for (int i = 0; i < statsHooks.length; i++)
			statsHooks[i].recordClassDefine(name, result, classbytes, classpathEntry, entry, this);
		return result;
	}

	/**
	 * Returns the host base data for this classpath manager
	 * @return the host base data for this classpath manager
	 */
	public BaseData getBaseData() {
		return data;
	}

	/**
	 * Returns the fragment classpaths of this classpath manager
	 * @return the fragment classpaths of this classpath manager
	 */
	public FragmentClasspath[] getFragmentClasspaths() {
		return fragments;
	}

	/**
	 * Returns the host classpath entries for this classpath manager
	 * @return the host classpath entries for this classpath manager
	 */
	public ClasspathEntry[] getHostClasspathEntries() {
		return entries;
	}

	/**
	 * Returns the base class loader used by this classpath manager
	 * @return the base class loader used by this classpath manager
	 */
	public BaseClassLoader getBaseClassLoader() {
		return classloader;
	}

	public String findLibrary(String libname) {
		synchronized (this) {
			if (loadedLibraries == null)
				loadedLibraries = new ArrayList(1);
		}
		synchronized (loadedLibraries) {
			// we assume that each classloader will load a small number of of libraries
			// instead of wasting space with a map we iterate over our collection of found libraries
			// each element is a String[2], each array is {"libname", "libpath"}
			for (Iterator libs = loadedLibraries.iterator(); libs.hasNext();) {
				String[] libNameResult = (String[]) libs.next();
				if (libNameResult[0].equals(libname))
					return libNameResult[1];
			}

			String result = classloader.getDelegate().findLibrary(libname);
			if (result != null)
				loadedLibraries.add(new String[] {libname, result});
			return result;
		}
	}

}
