/*******************************************************************************
 * Copyright (c) 2005, 2016 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.internal.loader.classpath;

import java.io.*;
import java.net.URL;
import java.util.*;
import org.eclipse.osgi.container.*;
import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent;
import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
import org.eclipse.osgi.framework.util.ArrayMap;
import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
import org.eclipse.osgi.internal.hookregistry.HookRegistry;
import org.eclipse.osgi.internal.loader.ModuleClassLoader;
import org.eclipse.osgi.internal.loader.ModuleClassLoader.DefineClassResult;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.internal.weaving.WeavingHookConfigurator;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.storage.NativeCodeFinder;
import org.eclipse.osgi.storage.Storage;
import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleException;
import org.osgi.framework.namespace.HostNamespace;

/**
 * A helper class for {@link ModuleClassLoader} implementations.  This class will keep track of 
 * {@link ClasspathEntry} objects for the host bundle and any attached fragment bundles.  This 
 * class takes care of searching the {@link ClasspathEntry} objects for a module class loader
 * implementation.  Additional behavior may be added to a classpath manager by configuring a 
 * {@link ClassLoaderHook}.
 * @see ModuleClassLoader
 * @see ClassLoaderHook
 * @since 3.2
 */
public class ClasspathManager {
	private static final FragmentClasspath[] emptyFragments = new FragmentClasspath[0];
	private static final String[] DEFAULT_CLASSPATH = new String[] {"."}; //$NON-NLS-1$
	@SuppressWarnings("unchecked")
	private static final Enumeration<URL> EMPTY_ENUMERATION = Collections.enumeration(Collections.EMPTY_LIST);

	private final Generation generation;
	private final ModuleClassLoader classloader;
	private final HookRegistry hookRegistry;
	private final Debug debug;

	// TODO Note that PDE has internal dependency on this field type/name (bug 267238)
	private final ClasspathEntry[] entries;
	// TODO Note that PDE has internal dependency on this field type/name (bug 267238)
	private volatile FragmentClasspath[] fragments;
	// a Map<String,String> where "libname" is the key and libpath" is the value
	private ArrayMap<String, String> loadedLibraries = null;
	// used to detect recusive defineClass calls for the same class on the same class loader (bug 345500)
	private ThreadLocal<Collection<String>> currentlyDefining = new ThreadLocal<>();

	/**
	 * Constructs a classpath manager for the given generation and module class loader
	 * @param generation the host generation for this classpath manager
	 * @param classloader the ModuleClassLoader for this classpath manager
	 */
	public ClasspathManager(Generation generation, ModuleClassLoader classloader) {
		EquinoxConfiguration configuration = generation.getBundleInfo().getStorage().getConfiguration();
		this.debug = configuration.getDebug();
		this.hookRegistry = configuration.getHookRegistry();
		this.generation = generation;
		this.classloader = classloader;
		String[] cp = getClassPath(generation.getRevision());
		this.fragments = buildFragmentClasspaths(this.classloader, this);
		this.entries = buildClasspath(cp, this, this.generation);
	}

	private static String[] getClassPath(ModuleRevision revision) {
		List<ModuleCapability> moduleDatas = revision.getModuleCapabilities(EquinoxModuleDataNamespace.MODULE_DATA_NAMESPACE);
		@SuppressWarnings("unchecked")
		List<String> cp = moduleDatas.isEmpty() ? null : (List<String>) moduleDatas.get(0).getAttributes().get(EquinoxModuleDataNamespace.CAPABILITY_CLASSPATH);
		return cp == null ? DEFAULT_CLASSPATH : cp.toArray(new String[cp.size()]);
	}

	private FragmentClasspath[] buildFragmentClasspaths(ModuleClassLoader hostloader, ClasspathManager manager) {
		if (hostloader == null) {
			return emptyFragments;
		}
		List<ModuleWire> fragmentWires = hostloader.getBundleLoader().getWiring().getProvidedModuleWires(HostNamespace.HOST_NAMESPACE);
		if (fragmentWires == null) {
			// we don't hold locks while checking the graph, just return if no longer valid
			return emptyFragments;
		}
		List<FragmentClasspath> result = new ArrayList<>(fragmentWires.size());
		for (ModuleWire fragmentWire : fragmentWires) {
			ModuleRevision revision = fragmentWire.getRequirer();
			Generation fragGeneration = (Generation) revision.getRevisionInfo();

			String[] cp = getClassPath(revision);
			ClasspathEntry[] fragEntries = buildClasspath(cp, manager, fragGeneration);
			FragmentClasspath fragClasspath = new FragmentClasspath(fragGeneration, fragEntries);
			insertFragment(fragClasspath, result);
		}

		return result.toArray(new FragmentClasspath[result.size()]);
	}

	private static void insertFragment(FragmentClasspath fragClasspath, List<FragmentClasspath> existing) {
		// Find a place in the fragment list to insert this fragment.
		long fragID = fragClasspath.getGeneration().getRevision().getRevisions().getModule().getId();

		for (ListIterator<FragmentClasspath> iExisting = existing.listIterator(); iExisting.hasNext();) {
			long otherID = iExisting.next().getGeneration().getRevision().getRevisions().getModule().getId();
			if (fragID < otherID) {
				iExisting.previous();
				iExisting.add(fragClasspath);
				return;
			}
		}
		existing.add(fragClasspath);
	}

	/**
	 * Closes all the classpath entry resources for this classpath manager.
	 *
	 */
	public void close() {
		for (int i = 0; i < entries.length; i++) {
			if (entries[i] != null) {
				try {
					entries[i].getBundleFile().close();
				} catch (IOException e) {
					generation.getBundleInfo().getStorage().getAdaptor().publishContainerEvent(ContainerEvent.ERROR, generation.getRevision().getRevisions().getModule(), e);
				}
			}
		}
		FragmentClasspath[] currentFragments = getFragmentClasspaths();
		for (int i = 0; i < currentFragments.length; i++)
			currentFragments[i].close();
	}

	private ClasspathEntry[] buildClasspath(String[] cp, ClasspathManager hostloader, Generation source) {
		ArrayList<ClasspathEntry> result = new ArrayList<>(cp.length);
		// add the regular classpath entries.
		for (int i = 0; i < cp.length; i++)
			findClassPathEntry(result, cp[i], hostloader, source);
		return 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 ClassLoaderHook#addClassPathEntry(ArrayList, String, ClasspathManager, Generation)}
	 * 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 sourceGeneration the source generation to search for the classpath
	 */
	private void findClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostloader, Generation sourceGeneration) {
		List<ClassLoaderHook> loaderHooks = hookRegistry.getClassLoaderHooks();
		boolean hookAdded = false;
		for (ClassLoaderHook hook : loaderHooks) {
			hookAdded |= hook.addClassPathEntry(result, cp, hostloader, sourceGeneration);
		}
		if (!addClassPathEntry(result, cp, hostloader, sourceGeneration) && !hookAdded) {
			BundleException be = new BundleException(NLS.bind(Msg.BUNDLE_CLASSPATH_ENTRY_NOT_FOUND_EXCEPTION, cp, sourceGeneration.getRevision().toString()), BundleException.MANIFEST_ERROR);
			sourceGeneration.getBundleInfo().getStorage().getAdaptor().publishContainerEvent(ContainerEvent.INFO, sourceGeneration.getRevision().getRevisions().getModule(), 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 hostManager the host classpath manager for the classpath
	 * @param source the source generation to search for the classpath
	 * @return true if a ClasspathEntry was added to the result
	 */
	public boolean addClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostManager, Generation source) {
		return addStandardClassPathEntry(result, cp, hostManager, source) || addEclipseClassPathEntry(result, cp, hostManager, source);
	}

	public static boolean addStandardClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostManager, Generation generation) {
		if (cp.equals(".")) { //$NON-NLS-1$
			result.add(hostManager.createClassPathEntry(generation.getBundleFile(), generation));
			return true;
		}
		ClasspathEntry element = hostManager.getClasspath(cp, generation);
		if (element != null) {
			result.add(element);
			return true;
		}
		// need to check in fragments for the classpath entry.
		// only check for fragments if the generation is the host's generation.
		if (hostManager.generation == generation) {
			FragmentClasspath[] hostFrags = hostManager.getFragmentClasspaths();
			for (int i = 0; i < hostFrags.length; i++) {
				FragmentClasspath fragCP = hostFrags[i];
				element = hostManager.getClasspath(cp, fragCP.getGeneration());
				if (element != null) {
					result.add(element);
					return true;
				}
			}
		}
		return false;
	}

	private boolean addEclipseClassPathEntry(ArrayList<ClasspathEntry> result, String cp, ClasspathManager hostManager, Generation source) {
		String var = hasPrefix(cp);
		if (var != null)
			// find internal library using eclipse predefined vars
			return addInternalClassPath(var, result, cp, hostManager, source);
		if (cp.startsWith(NativeCodeFinder.EXTERNAL_LIB_PREFIX)) {
			cp = cp.substring(NativeCodeFinder.EXTERNAL_LIB_PREFIX.length());
			// find external library using system property substitution
			ClasspathEntry cpEntry = hostManager.getExternalClassPath(source.getBundleInfo().getStorage().getConfiguration().substituteVars(cp), source);
			if (cpEntry != null) {
				result.add(cpEntry);
				return true;
			}
		}
		return false;
	}

	private boolean addInternalClassPath(String var, ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostManager, Generation source) {
		EquinoxConfiguration configuration = source.getBundleInfo().getStorage().getConfiguration();
		if (var.equals("ws")) //$NON-NLS-1$
			return ClasspathManager.addStandardClassPathEntry(cpEntries, "ws/" + configuration.getWS() + cp.substring(4), hostManager, source); //$NON-NLS-1$
		if (var.equals("os")) //$NON-NLS-1$
			return ClasspathManager.addStandardClassPathEntry(cpEntries, "os/" + configuration.getOS() + cp.substring(4), hostManager, source); //$NON-NLS-1$ 
		if (var.equals("nl")) { //$NON-NLS-1$
			cp = cp.substring(4);
			List<String> NL_JAR_VARIANTS = source.getBundleInfo().getStorage().getConfiguration().ECLIPSE_NL_JAR_VARIANTS;
			for (String nlVariant : NL_JAR_VARIANTS) {
				if (ClasspathManager.addStandardClassPathEntry(cpEntries, "nl/" + nlVariant + cp, hostManager, source)) //$NON-NLS-1$ 
					return true;
			}
		}
		return false;
	}

	//return a String representing the string found between the $s
	private static String hasPrefix(String libPath) {
		if (libPath.startsWith("$ws$")) //$NON-NLS-1$
			return "ws"; //$NON-NLS-1$
		if (libPath.startsWith("$os$")) //$NON-NLS-1$
			return "os"; //$NON-NLS-1$
		if (libPath.startsWith("$nl$")) //$NON-NLS-1$
			return "nl"; //$NON-NLS-1$
		return null;
	}

	/**
	 * Creates a new ClasspathEntry object for the requested classpath if the source exists.
	 * @param cp the requested classpath.
	 * @param cpGeneration the source generation to search for the classpath
	 * @return a new ClasspathEntry for the requested classpath or null if the source does not exist.
	 */
	public ClasspathEntry getClasspath(String cp, Generation cpGeneration) {
		BundleFile bundlefile = null;
		File file;
		BundleEntry cpEntry = cpGeneration.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, cpGeneration);
		// check for internal library jars
		else if ((file = cpGeneration.getBundleFile().getFile(cp, false)) != null)
			bundlefile = createBundleFile(file, cpGeneration);
		if (bundlefile != null)
			return createClassPathEntry(bundlefile, cpGeneration);
		return null;
	}

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

	public synchronized void loadFragments(Collection<ModuleRevision> addedFragments) {
		List<FragmentClasspath> result = new ArrayList<>(Arrays.asList(fragments));

		for (ModuleRevision addedFragment : addedFragments) {
			Generation fragGeneration = (Generation) addedFragment.getRevisionInfo();
			String[] cp = getClassPath(addedFragment);
			ClasspathEntry[] fragEntries = buildClasspath(cp, this, fragGeneration);
			FragmentClasspath fragClasspath = new FragmentClasspath(fragGeneration, fragEntries);
			insertFragment(fragClasspath, result);
		}

		fragments = result.toArray(new FragmentClasspath[result.size()]);
	}

	private static BundleFile createBundleFile(File content, Generation generation) {
		if (!content.exists()) {
			return null;
		}
		return generation.getBundleInfo().getStorage().createBundleFile(content, generation, content.isDirectory(), false);
	}

	private static BundleFile createBundleFile(String nestedDir, Generation generation) {
		return generation.getBundleInfo().getStorage().createNestedBundleFile(nestedDir, generation.getBundleFile(), generation);
	}

	private ClasspathEntry createClassPathEntry(BundleFile bundlefile, Generation source) {
		ClasspathEntry entry;
		if (classloader != null)
			entry = classloader.createClassPathEntry(bundlefile, source);
		else
			entry = new ClasspathEntry(bundlefile, source.getDomain(), source);
		return entry;
	}

	/**
	 * Finds a local resource by searching the ClasspathEntry objects of the classpath manager.
	 * This method will first call all the configured class loading hooks 
	 * {@link ClassLoaderHook#preFindLocalResource(String, ClasspathManager)} methods.  Then it 
	 * will search for the resource.  Finally it will call all the configured class loading hooks
	 * {@link ClassLoaderHook#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) {
		List<ClassLoaderHook> hooks = hookRegistry.getClassLoaderHooks();
		for (ClassLoaderHook hook : hooks) {
			hook.preFindLocalResource(resource, this);
		}
		URL result = null;
		try {
			result = findLocalResourceImpl(resource, -1);
			return result;
		} finally {
			for (ClassLoaderHook hook : hooks) {
				hook.postFindLocalResource(resource, result, this);
			}
		}
	}

	private URL findLocalResourceImpl(String resource, int classPathIndex) {
		URL result = null;
		int curIndex = 0;
		for (int i = 0; i < entries.length; i++) {
			if (entries[i] != null) {
				result = findResourceImpl(resource, entries[i].getBundleFile(), curIndex);
				if (result != null && (classPathIndex == -1 || classPathIndex == curIndex))
					return result;
			}
			curIndex++;
		}
		// look in fragments
		FragmentClasspath[] currentFragments = getFragmentClasspaths();
		for (int i = 0; i < currentFragments.length; i++) {
			ClasspathEntry[] fragEntries = currentFragments[i].getEntries();
			for (int j = 0; j < fragEntries.length; j++) {
				result = findResourceImpl(resource, fragEntries[j].getBundleFile(), curIndex);
				if (result != null && (classPathIndex == -1 || classPathIndex == curIndex))
					return result;
				curIndex++;
			}
		}
		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
	 */
	public Enumeration<URL> findLocalResources(String resource) {
		List<URL> resources = new ArrayList<>(6);
		int classPathIndex = 0;
		for (int i = 0; i < entries.length; i++) {
			if (entries[i] != null) {
				URL url = findResourceImpl(resource, entries[i].getBundleFile(), classPathIndex);
				if (url != null)
					resources.add(url);
			}
			classPathIndex++;
		}
		// look in fragments
		FragmentClasspath[] currentFragments = getFragmentClasspaths();
		for (int i = 0; i < currentFragments.length; i++) {
			ClasspathEntry[] fragEntries = currentFragments[i].getEntries();
			for (int j = 0; j < fragEntries.length; j++) {
				URL url = findResourceImpl(resource, fragEntries[j].getBundleFile(), classPathIndex);
				if (url != null)
					resources.add(url);
				classPathIndex++;
			}
		}
		if (resources.size() > 0)
			return Collections.enumeration(resources);
		return EMPTY_ENUMERATION;
	}

	private URL findResourceImpl(String name, BundleFile bundlefile, int index) {
		return bundlefile.getResourceURL(name, generation.getRevision().getRevisions().getModule(), 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) {
		return findLocalEntry(path, -1);
	}

	/**
	 * Finds a local entry by searching the ClasspathEntry with the specified
	 * class path index.
	 * @param path the requested entry path.
	 * @param classPathIndex the index of the ClasspathEntry to search
	 * @return the requested entry or null if the entry does not exist
	 */
	public BundleEntry findLocalEntry(String path, int classPathIndex) {
		BundleEntry result = null;
		int curIndex = 0;
		for (int i = 0; i < entries.length; i++) {
			if (entries[i] != null) {
				result = findEntryImpl(path, entries[i].getBundleFile());
				if (result != null && (classPathIndex == -1 || classPathIndex == curIndex))
					return result;
			}
			curIndex++;
		}
		// look in fragments
		FragmentClasspath[] currentFragments = getFragmentClasspaths();
		for (int i = 0; i < currentFragments.length; i++) {
			ClasspathEntry[] fragEntries = currentFragments[i].getEntries();
			for (int j = 0; j < fragEntries.length; j++) {
				result = findEntryImpl(path, fragEntries[j].getBundleFile());
				if (result != null && (classPathIndex == -1 || classPathIndex == curIndex))
					return result;
				curIndex++;
			}
		}
		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<BundleEntry> findLocalEntries(String path) {
		List<BundleEntry> objects = new ArrayList<>(6);
		for (int i = 0; i < entries.length; i++) {
			if (entries[i] != null) {
				BundleEntry result = findEntryImpl(path, entries[i].getBundleFile());
				if (result != null)
					objects.add(result);
			}
		}
		// look in fragments
		FragmentClasspath[] currentFragments = getFragmentClasspaths();
		for (int i = 0; i < currentFragments.length; i++) {
			ClasspathEntry[] fragEntries = currentFragments[i].getEntries();
			for (int j = 0; j < fragEntries.length; j++) {
				BundleEntry result = findEntryImpl(path, fragEntries[j].getBundleFile());
				if (result != null)
					objects.add(result);
			}
		}
		if (objects.size() > 0)
			return Collections.enumeration(objects);
		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 loader hooks 
	 * {@link ClassLoaderHook#preFindLocalClass(String, ClasspathManager)} methods.  Then it 
	 * will search for the class.  If a class is found then
	 * <ol>
	 *   <li>All configured class loader hooks
	 *       {@link ClassLoaderHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
	 *       methods will be called.</li>
	 *   <li>The class is then defined.</li>  
	 *   <li>Finally, all configured class loading 
	 *       stats hooks {@link ClassLoaderHook#recordClassDefine(String, Class, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
	 *       methods are called.</li>
	 * </ol>
	 * Finally all the configured class loading hooks
	 * {@link ClassLoaderHook#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;
		List<ClassLoaderHook> hooks = hookRegistry.getClassLoaderHooks();
		try {
			for (ClassLoaderHook hook : hooks) {
				hook.preFindLocalClass(classname, this);
			}
			result = classloader.publicFindLoaded(classname);
			if (result != null)
				return result;
			result = findLocalClassImpl(classname, hooks);
			return result;
		} finally {
			for (ClassLoaderHook hook : hooks) {
				hook.postFindLocalClass(classname, result, this);
			}
		}
	}

	private Class<?> findLocalClassImpl(String classname, List<ClassLoaderHook> hooks) throws ClassNotFoundException {
		Class<?> result = null;
		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.
		FragmentClasspath[] currentFragments = getFragmentClasspaths();
		for (int i = 0; i < currentFragments.length; i++) {
			ClasspathEntry[] fragEntries = currentFragments[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, List<ClassLoaderHook> hooks) {
		if (debug.DEBUG_LOADER)
			Debug.println("ModuleClassLoader[" + classloader.getBundleLoader() + " - " + classpathEntry.getBundleFile() + "].findClassImpl(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
		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_LOADER)
				Debug.println("  IOException reading " + filename + " from " + classpathEntry.getBundleFile()); //$NON-NLS-1$ //$NON-NLS-2$
			throw (LinkageError) new LinkageError("Error reading class bytes: " + name).initCause(e); //$NON-NLS-1$
		}
		if (debug.DEBUG_LOADER) {
			Debug.println("  read " + classbytes.length + " bytes from " + classpathEntry.getBundleFile() + "!/" + filename); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			Debug.println("  defining class " + name); //$NON-NLS-1$
		}

		Collection<String> current = currentlyDefining.get();
		if (current == null) {
			current = new ArrayList<>(5);
			currentlyDefining.set(current);
		}
		if (current.contains(name))
			return null; // avoid recursive defines (bug 345500)
		try {
			current.add(name);
			return defineClass(name, classbytes, classpathEntry, entry, hooks);
		} catch (Error e) {
			if (debug.DEBUG_LOADER)
				Debug.println("  error defining class " + name); //$NON-NLS-1$
			throw e;
		} finally {
			current.remove(name);
		}
	}

	/**
	 * Defines the specified class.  This method will first call all the configured class loader hooks 
	 * {@link ClassLoadingHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)} 
	 * methods.  If any hook modifies the bytes the all configured hook 
	 * {@link ClassLoaderHook#rejectTransformation(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)} 
	 * methods are called.  Then it will call the {@link ModuleClassLoader#defineClass(String, byte[], ClasspathEntry, BundleEntry)}
	 * method to define the class. After that, the class loader hooks are called to announce the class
	 * definition by calling {@link ClassLoaderHook#recordClassDefine(String, Class, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}.
	 * @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 hooks the class loader hooks
	 * @return the defined class
	 */
	private Class<?> defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, List<ClassLoaderHook> hooks) {
		DefineClassResult result = null;
		try {
			definePackage(name, classpathEntry);
			for (ClassLoaderHook hook : hooks) {
				byte[] modifiedBytes = hook.processClass(name, classbytes, classpathEntry, entry, this);
				if (modifiedBytes != null) {
					// the WeavingHookConfigurator already calls the rejectTransformation method; avoid calling it again.
					if (!(hook instanceof WeavingHookConfigurator)) {
						for (ClassLoaderHook rejectHook : hooks) {
							if (rejectHook.rejectTransformation(name, modifiedBytes, classpathEntry, entry, this)) {
								modifiedBytes = null;
								break;
							}
						}
					}
					if (modifiedBytes != null) {
						classbytes = modifiedBytes;
					}
				}
			}
			result = classloader.defineClass(name, classbytes, classpathEntry);
		} finally {
			// only pass the newly defined class to the hook
			Class<?> defined = result != null && result.defined ? result.clazz : null;
			for (ClassLoaderHook hook : hooks) {
				hook.recordClassDefine(name, defined, classbytes, classpathEntry, entry, this);
			}
		}
		// return either the pre-loaded class or the newly defined class
		return result == null ? null : result.clazz;
	}

	private void definePackage(String name, ClasspathEntry classpathEntry) {
		// Define the package if it is not the default package.
		int lastIndex = name.lastIndexOf('.');
		if (lastIndex < 0) {
			return;
		}
		String packageName = name.substring(0, lastIndex);
		Object pkg = classloader.publicGetPackage(packageName);
		if (pkg != null) {
			return;
		}

		// get info about the package from the classpath entry's manifest.
		String specTitle = null, specVersion = null, specVendor = null, implTitle = null, implVersion = null, implVendor = null;

		if (generation.getBundleInfo().getStorage().getConfiguration().DEFINE_PACKAGE_ATTRIBUTES) {
			ManifestPackageAttributes manifestPackageAttributes = classpathEntry.manifestPackageAttributesFor(packageName);
			TitleVersionVendor specification = manifestPackageAttributes.getSpecification();
			TitleVersionVendor implementation = manifestPackageAttributes.getImplementation();
			specTitle = specification.getTitle();
			specVersion = specification.getVersion();
			specVendor = specification.getVendor();
			implTitle = implementation.getTitle();
			implVersion = implementation.getVersion();
			implVendor = implementation.getVendor();
		}

		// The package is not defined yet define it before we define the class.
		// TODO still need to seal packages.
		classloader.publicDefinePackage(packageName, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, null);
	}

	/**
	 * 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;
	}

	/**
	 * Finds a library for the bundle represented by this class path manager
	 * @param libname the library name
	 * @return The absolution path to the library or null if not found
	 */
	public String findLibrary(String libname) {
		synchronized (this) {
			if (loadedLibraries == null)
				loadedLibraries = new ArrayMap<>(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"}
			String libpath = loadedLibraries.get(libname);
			if (libpath != null)
				return libpath;

			libpath = findLibrary0(libname);
			if (libpath != null)
				loadedLibraries.put(libname, libpath);
			return libpath;
		}
	}

	private String findLibrary0(String libname) {
		List<ClassLoaderHook> hooks = hookRegistry.getClassLoaderHooks();
		String result = null;
		for (ClassLoaderHook hook : hooks) {
			try {
				result = hook.preFindLibrary(libname, classloader);
				if (result != null) {
					return result;
				}
			} catch (FileNotFoundException e) {
				return null;
			}
		}

		result = generation.findLibrary(libname);
		if (result != null) {
			return result;
		}

		// look in fragment generations
		FragmentClasspath[] currentFragments = getFragmentClasspaths();
		for (FragmentClasspath fragment : currentFragments) {
			result = fragment.getGeneration().findLibrary(libname);
			if (result != null) {
				return result;
			}
		}

		for (ClassLoaderHook hook : hooks) {
			result = hook.postFindLibrary(libname, classloader);
			if (result != null) {
				return result;
			}
		}
		return result;
	}

	/**
	 * @see ModuleClassLoader#findEntries(String, String, int)
	 */
	public List<URL> findEntries(String path, String filePattern, int options) {
		List<Generation> generations = new ArrayList<>();
		// first get the host bundle file
		generations.add(generation);
		// next get the attached fragments bundle files
		FragmentClasspath[] currentFragments = getFragmentClasspaths();
		for (FragmentClasspath fragmentClasspath : currentFragments)
			generations.add(fragmentClasspath.getGeneration());

		List<URL> result = Collections.<URL> emptyList();
		// now search over all the bundle files
		Enumeration<URL> eURLs = Storage.findEntries(generations, path, filePattern, options);
		if (eURLs == null)
			return result;
		result = new ArrayList<>();
		while (eURLs.hasMoreElements())
			result.add(eURLs.nextElement());
		return Collections.unmodifiableList(result);
	}

	/**
	 * @see ModuleClassLoader#listLocalResources(String, String, int)
	 */
	public Collection<String> listLocalResources(String path, String filePattern, int options) {
		List<BundleFile> bundleFiles = new ArrayList<>();

		ClasspathEntry[] cpEntries = getHostClasspathEntries();
		for (ClasspathEntry cpEntry : cpEntries)
			bundleFiles.add(cpEntry.getBundleFile());

		FragmentClasspath[] currentFragments = getFragmentClasspaths();
		for (FragmentClasspath fragmentClasspath : currentFragments) {
			ClasspathEntry[] fragEntries = fragmentClasspath.getEntries();
			for (ClasspathEntry cpEntry : fragEntries)
				bundleFiles.add(cpEntry.getBundleFile());
		}

		return Storage.listEntryPaths(bundleFiles, path, filePattern, options);
	}

	public Generation getGeneration() {
		return generation;
	}

	public ModuleClassLoader getClassLoader() {
		return classloader;
	}
}
