/*******************************************************************************
 * Copyright (c) 2004, 2009 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;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import org.eclipse.osgi.framework.adaptor.*;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.internal.core.*;
import org.eclipse.osgi.framework.util.KeyedHashSet;
import org.eclipse.osgi.internal.loader.buddy.PolicyHandler;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkEvent;

/**
 * This object is responsible for all classloader delegation for a bundle.
 * It represents the loaded state of the bundle.  BundleLoader objects
 * are created lazily; care should be taken not to force the creation
 * of a BundleLoader unless it is necessary.
 * @see org.eclipse.osgi.internal.loader.BundleLoaderProxy
 */
public class BundleLoader implements ClassLoaderDelegate {
	public final static String DEFAULT_PACKAGE = "."; //$NON-NLS-1$
	public final static String JAVA_PACKAGE = "java."; //$NON-NLS-1$
	public final static byte FLAG_IMPORTSINIT = 0x01;
	public final static byte FLAG_HASDYNAMICIMPORTS = 0x02;
	public final static byte FLAG_HASDYNAMICEIMPORTALL = 0x04;
	public final static byte FLAG_CLOSED = 0x08;

	public final static ClassContext CLASS_CONTEXT = (ClassContext) AccessController.doPrivileged(new PrivilegedAction() {
		public Object run() {
			return new ClassContext();
		}
	});
	public final static ClassLoader FW_CLASSLOADER = getClassLoader(Framework.class);

	private static final int PRE_CLASS = 1;
	private static final int POST_CLASS = 2;
	private static final int PRE_RESOURCE = 3;
	private static final int POST_RESOURCE = 4;
	private static final int PRE_RESOURCES = 5;
	private static final int POST_RESOURCES = 6;
	private static final int PRE_LIBRARY = 7;
	private static final int POST_LIBRARY = 8;

	private static final boolean USE_GLOBAL_DEADLOCK_AVOIDANCE_LOCK = "true".equals(BundleLoaderProxy.secureAction.getProperty("osgi.classloader.singleThreadLoads")); //$NON-NLS-1$//$NON-NLS-2$
	private static final List waitingList = USE_GLOBAL_DEADLOCK_AVOIDANCE_LOCK ? new ArrayList(0) : null;
	private static Object lockThread;
	private static int lockCount = 0;

	/* the proxy */
	final private BundleLoaderProxy proxy;
	/* Bundle object */
	final BundleHost bundle;
	final private PolicyHandler policy;
	/* List of package names that are exported by this BundleLoader */
	final private Collection exportedPackages;
	final private Collection substitutedPackages;
	/* List of required bundle BundleLoaderProxy objects */
	final BundleLoaderProxy[] requiredBundles;
	/* List of indexes into the requiredBundles list of reexported bundles */
	final int[] reexportTable;
	/* cache of required package sources. Key is packagename, value is PackageSource */
	final private KeyedHashSet requiredSources;

	// note that the following non-final must be access using synchronization
	/* cache of imported packages. Key is packagename, Value is PackageSource */
	private KeyedHashSet importedSources;
	/* If not null, list of package stems to import dynamically. */
	private String[] dynamicImportPackageStems;
	/* If not null, list of package names to import dynamically. */
	private String[] dynamicImportPackages;
	/* loader flags */
	private byte loaderFlags = 0;
	/* The is the BundleClassLoader for the bundle */
	private BundleClassLoader classloader;
	private ClassLoader parent;

	/**
	 * Returns the package name from the specified class name.
	 * The returned package is dot seperated.
	 *
	 * @param name   Name of a class.
	 * @return Dot separated package name or null if the class
	 *         has no package name.
	 */
	public final static String getPackageName(String name) {
		if (name != null) {
			int index = name.lastIndexOf('.'); /* find last period in class name */
			if (index > 0)
				return name.substring(0, index);
		}
		return DEFAULT_PACKAGE;
	}

	/**
	 * Returns the package name from the specified resource name.
	 * The returned package is dot seperated.
	 *
	 * @param name   Name of a resource.
	 * @return Dot separated package name or null if the resource
	 *         has no package name.
	 */
	public final static String getResourcePackageName(String name) {
		if (name != null) {
			/* check for leading slash*/
			int begin = ((name.length() > 1) && (name.charAt(0) == '/')) ? 1 : 0;
			int end = name.lastIndexOf('/'); /* index of last slash */
			if (end > begin)
				return name.substring(begin, end).replace('/', '.');
		}
		return DEFAULT_PACKAGE;
	}

	/**
	 * BundleLoader runtime constructor. This object is created lazily
	 * when the first request for a resource is made to this bundle.
	 *
	 * @param bundle Bundle object for this loader.
	 * @param proxy the BundleLoaderProxy for this loader.
	 * @exception org.osgi.framework.BundleException
	 */
	protected BundleLoader(BundleHost bundle, BundleLoaderProxy proxy) throws BundleException {
		this.bundle = bundle;
		this.proxy = proxy;
		try {
			bundle.getBundleData().open(); /* make sure the BundleData is open */
		} catch (IOException e) {
			throw new BundleException(Msg.BUNDLE_READ_EXCEPTION, e);
		}
		BundleDescription description = proxy.getBundleDescription();
		// init the require bundles list.
		BundleDescription[] required = description.getResolvedRequires();
		if (required.length > 0) {
			// get a list of re-exported symbolic names
			HashSet reExportSet = new HashSet(required.length);
			BundleSpecification[] requiredSpecs = description.getRequiredBundles();
			if (requiredSpecs != null && requiredSpecs.length > 0)
				for (int i = 0; i < requiredSpecs.length; i++)
					if (requiredSpecs[i].isExported())
						reExportSet.add(requiredSpecs[i].getName());

			requiredBundles = new BundleLoaderProxy[required.length];
			int[] reexported = new int[required.length];
			int reexportIndex = 0;
			for (int i = 0; i < required.length; i++) {
				requiredBundles[i] = getLoaderProxy(required[i]);
				if (reExportSet.contains(required[i].getSymbolicName()))
					reexported[reexportIndex++] = i;
			}
			if (reexportIndex > 0) {
				reexportTable = new int[reexportIndex];
				System.arraycopy(reexported, 0, reexportTable, 0, reexportIndex);
			} else {
				reexportTable = null;
			}
			requiredSources = new KeyedHashSet(10, false);
		} else {
			requiredBundles = null;
			reexportTable = null;
			requiredSources = null;
		}

		// init the provided packages set
		ExportPackageDescription[] exports = description.getSelectedExports();
		if (exports != null && exports.length > 0) {
			exportedPackages = Collections.synchronizedCollection(exports.length > 10 ? (Collection) new HashSet(exports.length) : new ArrayList(exports.length));
			initializeExports(exports, exportedPackages);
		} else {
			exportedPackages = Collections.synchronizedCollection(new ArrayList(0));
		}

		ExportPackageDescription substituted[] = description.getSubstitutedExports();
		if (substituted.length > 0) {
			substitutedPackages = substituted.length > 10 ? (Collection) new HashSet(substituted.length) : new ArrayList(substituted.length);
			for (int i = 0; i < substituted.length; i++)
				substitutedPackages.add(substituted[i].getName());
		} else {
			substitutedPackages = null;
		}

		//This is the fastest way to access to the description for fragments since the hostdescription.getFragments() is slow
		BundleFragment[] fragmentObjects = bundle.getFragments();
		BundleDescription[] fragments = new BundleDescription[fragmentObjects == null ? 0 : fragmentObjects.length];
		for (int i = 0; i < fragments.length; i++)
			fragments[i] = fragmentObjects[i].getBundleDescription();
		// init the dynamic imports tables
		if (description.hasDynamicImports())
			addDynamicImportPackage(description.getImportPackages());
		// ...and its fragments
		for (int i = 0; i < fragments.length; i++)
			if (fragments[i].isResolved() && fragments[i].hasDynamicImports())
				addDynamicImportPackage(fragments[i].getImportPackages());

		//Initialize the policy handler
		String buddyList = null;
		try {
			buddyList = (String) bundle.getBundleData().getManifest().get(Constants.BUDDY_LOADER);
		} catch (BundleException e) {
			// do nothing; buddyList == null
		}
		policy = buddyList != null ? new PolicyHandler(this, buddyList, bundle.getFramework().getPackageAdmin()) : null;
		if (policy != null)
			policy.open(bundle.getFramework().getSystemBundleContext());
	}

	private void initializeExports(ExportPackageDescription[] exports, Collection exportNames) {
		for (int i = 0; i < exports.length; i++) {
			if (proxy.forceSourceCreation(exports[i])) {
				if (!exportNames.contains(exports[i].getName())) {
					// must force filtered and reexport sources to be created early
					// to prevent lazy normal package source creation.
					// We only do this for the first export of a package name. 
					proxy.createPackageSource(exports[i], true);
				}
			}
			exportNames.add(exports[i].getName());
		}
	}

	public synchronized KeyedHashSet getImportedSources(KeyedHashSet visited) {
		if ((loaderFlags & FLAG_IMPORTSINIT) != 0)
			return importedSources;
		BundleDescription bundleDesc = proxy.getBundleDescription();
		ExportPackageDescription[] packages = bundleDesc.getResolvedImports();
		if (packages != null && packages.length > 0) {
			if (importedSources == null)
				importedSources = new KeyedHashSet(packages.length, false);
			for (int i = 0; i < packages.length; i++) {
				if (packages[i].getExporter() == bundleDesc)
					continue; // ignore imports resolved to this bundle
				PackageSource source = createExportPackageSource(packages[i], visited);
				if (source != null)
					importedSources.add(source);
			}
		}
		loaderFlags |= FLAG_IMPORTSINIT;
		return importedSources;
	}

	final PackageSource createExportPackageSource(ExportPackageDescription export, KeyedHashSet visited) {
		BundleLoaderProxy exportProxy = getLoaderProxy(export.getExporter());
		if (exportProxy == null)
			// TODO log error!!
			return null;
		PackageSource requiredSource = exportProxy.getBundleLoader().findRequiredSource(export.getName(), visited);
		PackageSource exportSource = exportProxy.createPackageSource(export, false);
		if (requiredSource == null)
			return exportSource;
		return createMultiSource(export.getName(), new PackageSource[] {requiredSource, exportSource});
	}

	private static PackageSource createMultiSource(String packageName, PackageSource[] sources) {
		if (sources.length == 1)
			return sources[0];
		ArrayList sourceList = new ArrayList(sources.length);
		for (int i = 0; i < sources.length; i++) {
			SingleSourcePackage[] innerSources = sources[i].getSuppliers();
			for (int j = 0; j < innerSources.length; j++)
				if (!sourceList.contains(innerSources[j]))
					sourceList.add(innerSources[j]);
		}
		return new MultiSourcePackage(packageName, (SingleSourcePackage[]) sourceList.toArray(new SingleSourcePackage[sourceList.size()]));
	}

	/*
	 * get the loader proxy for a bundle description
	 */
	public final BundleLoaderProxy getLoaderProxy(BundleDescription source) {
		BundleLoaderProxy sourceProxy = (BundleLoaderProxy) source.getUserObject();
		if (sourceProxy == null) {
			// may need to force the proxy to be created
			long exportingID = source.getBundleId();
			BundleHost exportingBundle = (BundleHost) bundle.getFramework().getBundle(exportingID);
			if (exportingBundle == null)
				return null;
			sourceProxy = exportingBundle.getLoaderProxy();
		}
		return sourceProxy;
	}

	/*
	 * Close the the BundleLoader.
	 *
	 */
	synchronized void close() {
		if ((loaderFlags & FLAG_CLOSED) != 0)
			return;
		if (classloader != null)
			classloader.close();
		if (policy != null)
			policy.close(bundle.getFramework().getSystemBundleContext());
		loaderFlags |= FLAG_CLOSED; /* This indicates the BundleLoader is destroyed */
	}

	/**
	 * This method loads a class from the bundle.  The class is searched for in the
	 * same manner as it would if it was being loaded from a bundle (i.e. all
	 * hosts, fragments, import, required bundles and local resources are searched.
	 *
	 * @param      name     the name of the desired Class.
	 * @return     the resulting Class
	 * @exception  java.lang.ClassNotFoundException  if the class definition was not found.
	 */
	final public Class loadClass(String name) throws ClassNotFoundException {
		BundleClassLoader bcl = createClassLoader();
		// The instanceof check here is just to be safe.  The javadoc contract stated in BundleClassLoader
		// mandate that BundleClassLoaders be an instance of ClassLoader.
		if (name.length() > 0 && name.charAt(0) == '[' && bcl instanceof ClassLoader)
			return Class.forName(name, false, (ClassLoader) bcl);
		return bcl.loadClass(name);
	}

	/**
	 * This method gets a resource from the bundle.  The resource is searched 
	 * for in the same manner as it would if it was being loaded from a bundle 
	 * (i.e. all hosts, fragments, import, required bundles and 
	 * local resources are searched).
	 *
	 * @param name the name of the desired resource.
	 * @return the resulting resource URL or null if it does not exist.
	 */
	final URL getResource(String name) {
		return createClassLoader().getResource(name);
	}

	public final synchronized ClassLoader getParentClassLoader() {
		if (parent != null)
			return parent;
		createClassLoader();
		return parent;
	}

	final public synchronized BundleClassLoader createClassLoader() {
		if (classloader != null)
			return classloader;
		String[] classpath;
		try {
			classpath = bundle.getBundleData().getClassPath();
		} catch (BundleException e) {
			// no classpath
			classpath = new String[0];
			bundle.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, e);
		}
		if (classpath == null) {
			// no classpath
			classpath = new String[0];
			bundle.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, new BundleException(Msg.BUNDLE_NO_CLASSPATH_MATCH, BundleException.MANIFEST_ERROR));
		}
		BundleClassLoader bcl = createBCLPrevileged(bundle.getProtectionDomain(), classpath);
		parent = getParentPrivileged(bcl);
		classloader = bcl;
		return classloader;
	}

	/**
	 * Finds a class local to this bundle.  Only the classloader for this bundle is searched.
	 * @param name The name of the class to find.
	 * @return The loaded Class or null if the class is not found.
	 * @throws ClassNotFoundException 
	 */
	Class findLocalClass(String name) throws ClassNotFoundException {
		if (Debug.DEBUG && Debug.DEBUG_LOADER)
			Debug.println("BundleLoader[" + this + "].findLocalClass(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		try {
			Class clazz = createClassLoader().findLocalClass(name);
			if (Debug.DEBUG && Debug.DEBUG_LOADER && clazz != null)
				Debug.println("BundleLoader[" + this + "] found local class " + name); //$NON-NLS-1$ //$NON-NLS-2$
			return clazz;
		} catch (ClassNotFoundException e) {
			if (e instanceof StatusException) {
				if ((((StatusException) e).getStatusCode() & StatusException.CODE_ERROR) != 0)
					throw e;
			}
			return null;
		}
	}

	/**
	 * Finds the class for a bundle.  This method is used for delegation by the bundle's classloader.
	 */
	public Class findClass(String name) throws ClassNotFoundException {
		return findClass(name, true);
	}

	Class findClass(String name, boolean checkParent) throws ClassNotFoundException {
		ClassLoader parentCL = getParentClassLoader();
		if (checkParent && parentCL != null && name.startsWith(JAVA_PACKAGE))
			// 1) if startsWith "java." delegate to parent and terminate search
			// we want to throw ClassNotFoundExceptions if a java.* class cannot be loaded from the parent.
			return parentCL.loadClass(name);
		try {
			if (USE_GLOBAL_DEADLOCK_AVOIDANCE_LOCK)
				lock(createClassLoader());
			return findClassInternal(name, checkParent, parentCL);
		} finally {
			if (USE_GLOBAL_DEADLOCK_AVOIDANCE_LOCK)
				unlock();
		}
	}

	private Class findClassInternal(String name, boolean checkParent, ClassLoader parentCL) throws ClassNotFoundException {
		if (Debug.DEBUG && Debug.DEBUG_LOADER)
			Debug.println("BundleLoader[" + this + "].loadBundleClass(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		String pkgName = getPackageName(name);
		boolean bootDelegation = false;
		// follow the OSGi delegation model
		if (checkParent && parentCL != null && bundle.getFramework().isBootDelegationPackage(pkgName))
			// 2) if part of the bootdelegation list then delegate to parent and continue of failure
			try {
				return parentCL.loadClass(name);
			} catch (ClassNotFoundException cnfe) {
				// we want to continue
				bootDelegation = true;
			}
		Class result = null;
		try {
			result = (Class) searchHooks(name, PRE_CLASS);
		} catch (ClassNotFoundException e) {
			throw e;
		} catch (FileNotFoundException e) {
			// will not happen
		}
		if (result != null)
			return result;
		// 3) search the imported packages
		PackageSource source = findImportedSource(pkgName, null);
		if (source != null) {
			// 3) found import source terminate search at the source
			result = source.loadClass(name);
			if (result != null)
				return result;
			throw new ClassNotFoundException(name);
		}
		// 4) search the required bundles
		source = findRequiredSource(pkgName, null);
		if (source != null)
			// 4) attempt to load from source but continue on failure
			result = source.loadClass(name);
		// 5) search the local bundle
		if (result == null)
			result = findLocalClass(name);
		if (result != null)
			return result;
		// 6) attempt to find a dynamic import source; only do this if a required source was not found
		if (source == null) {
			source = findDynamicSource(pkgName);
			if (source != null) {
				result = source.loadClass(name);
				if (result != null)
					return result;
				// must throw CNFE if dynamic import source does not have the class
				throw new ClassNotFoundException(name);
			}
		}

		if (result == null)
			try {
				result = (Class) searchHooks(name, POST_CLASS);
			} catch (ClassNotFoundException e) {
				throw e;
			} catch (FileNotFoundException e) {
				// will not happen
			}
		// do buddy policy loading
		if (result == null && policy != null)
			result = policy.doBuddyClassLoading(name);
		if (result != null)
			return result;
		// hack to support backwards compatibiility for bootdelegation
		// or last resort; do class context trick to work around VM bugs
		if (parentCL != null && !bootDelegation && ((checkParent && bundle.getFramework().compatibiltyBootDelegation) || isRequestFromVM()))
			// we don't need to continue if a CNFE is thrown here.
			try {
				return parentCL.loadClass(name);
			} catch (ClassNotFoundException e) {
				// we want to generate our own exception below
			}
		throw new ClassNotFoundException(name);
	}

	private Object searchHooks(String name, int type) throws ClassNotFoundException, FileNotFoundException {
		ClassLoaderDelegateHook[] delegateHooks = bundle.getFramework().getDelegateHooks();
		if (delegateHooks == null)
			return null;
		Object result = null;
		for (int i = 0; i < delegateHooks.length && result == null; i++) {
			switch (type) {
				case PRE_CLASS :
					result = delegateHooks[i].preFindClass(name, createClassLoader(), bundle.getBundleData());
					break;
				case POST_CLASS :
					result = delegateHooks[i].postFindClass(name, createClassLoader(), bundle.getBundleData());
					break;
				case PRE_RESOURCE :
					result = delegateHooks[i].preFindResource(name, createClassLoader(), bundle.getBundleData());
					break;
				case POST_RESOURCE :
					result = delegateHooks[i].postFindResource(name, createClassLoader(), bundle.getBundleData());
					break;
				case PRE_RESOURCES :
					result = delegateHooks[i].preFindResources(name, createClassLoader(), bundle.getBundleData());
					break;
				case POST_RESOURCES :
					result = delegateHooks[i].postFindResources(name, createClassLoader(), bundle.getBundleData());
					break;
				case PRE_LIBRARY :
					result = delegateHooks[i].preFindLibrary(name, createClassLoader(), bundle.getBundleData());
					break;
				case POST_LIBRARY :
					result = delegateHooks[i].postFindLibrary(name, createClassLoader(), bundle.getBundleData());
					break;
			}
		}
		return result;
	}

	private boolean isRequestFromVM() {
		if (bundle.getFramework().isBootDelegationPackage("*") || !bundle.getFramework().contextBootDelegation) //$NON-NLS-1$
			return false;
		// works around VM bugs that require all classloaders to have access to parent packages
		Class[] context = CLASS_CONTEXT.getClassContext();
		if (context == null || context.length < 2)
			return false;
		// skip the first class; it is the ClassContext class
		for (int i = 1; i < context.length; i++)
			// find the first class in the context which is not BundleLoader or instanceof ClassLoader
			if (context[i] != BundleLoader.class && !ClassLoader.class.isAssignableFrom(context[i])) {
				// only find in parent if the class is not "Class" (Class#forName case) or if the class is not loaded with a BundleClassLoader
				ClassLoader cl = getClassLoader(context[i]);
				if (cl != FW_CLASSLOADER) { // extra check incase an adaptor adds another class into the stack besides an instance of ClassLoader
					if (Class.class != context[i] && !(cl instanceof BundleClassLoader))
						return true;
					break;
				}
			}
		return false;
	}

	private static ClassLoader getClassLoader(final Class clazz) {
		if (System.getSecurityManager() == null)
			return clazz.getClassLoader();
		return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
			public Object run() {
				return clazz.getClassLoader();
			}
		});
	}

	/**
	 * Finds the resource for a bundle.  This method is used for delegation by the bundle's classloader.
	 */
	public URL findResource(String name) {
		return findResource(name, true);
	}

	URL findResource(String name, boolean checkParent) {
		if ((name.length() > 1) && (name.charAt(0) == '/')) /* if name has a leading slash */
			name = name.substring(1); /* remove leading slash before search */
		String pkgName = getResourcePackageName(name);
		boolean bootDelegation = false;
		ClassLoader parentCL = getParentClassLoader();
		// follow the OSGi delegation model
		// First check the parent classloader for system resources, if it is a java resource.
		if (checkParent && parentCL != null) {
			if (pkgName.startsWith(JAVA_PACKAGE))
				// 1) if startsWith "java." delegate to parent and terminate search
				// we never delegate java resource requests past the parent
				return parentCL.getResource(name);
			else if (bundle.getFramework().isBootDelegationPackage(pkgName)) {
				// 2) if part of the bootdelegation list then delegate to parent and continue of failure
				URL result = parentCL.getResource(name);
				if (result != null)
					return result;
				bootDelegation = true;
			}
		}

		URL result = null;
		try {
			result = (URL) searchHooks(name, PRE_RESOURCE);
		} catch (FileNotFoundException e) {
			return null;
		} catch (ClassNotFoundException e) {
			// will not happen
		}
		if (result != null)
			return result;
		// 3) search the imported packages
		PackageSource source = findImportedSource(pkgName, null);
		if (source != null)
			// 3) found import source terminate search at the source
			return source.getResource(name);
		// 4) search the required bundles
		source = findRequiredSource(pkgName, null);
		if (source != null)
			// 4) attempt to load from source but continue on failure
			result = source.getResource(name);
		// 5) search the local bundle
		if (result == null)
			result = findLocalResource(name);
		if (result != null)
			return result;
		// 6) attempt to find a dynamic import source; only do this if a required source was not found
		if (source == null) {
			source = findDynamicSource(pkgName);
			if (source != null)
				// must return the result of the dynamic import and do not continue
				return source.getResource(name);
		}

		if (result == null)
			try {
				result = (URL) searchHooks(name, POST_RESOURCE);
			} catch (FileNotFoundException e) {
				return null;
			} catch (ClassNotFoundException e) {
				// will not happen
			}
		// do buddy policy loading
		if (result == null && policy != null)
			result = policy.doBuddyResourceLoading(name);
		if (result != null)
			return result;
		// hack to support backwards compatibiility for bootdelegation
		// or last resort; do class context trick to work around VM bugs
		if (parentCL != null && !bootDelegation && ((checkParent && bundle.getFramework().compatibiltyBootDelegation) || isRequestFromVM()))
			// we don't need to continue if the resource is not found here
			return parentCL.getResource(name);
		return result;
	}

	/**
	 * Finds the resources for a bundle.  This  method is used for delegation by the bundle's classloader.
	 */
	public Enumeration findResources(String name) throws IOException {
		// do not delegate to parent because ClassLoader#getResources already did and it is final!!
		if ((name.length() > 1) && (name.charAt(0) == '/')) /* if name has a leading slash */
			name = name.substring(1); /* remove leading slash before search */
		String pkgName = getResourcePackageName(name);
		Enumeration result = null;
		try {
			result = (Enumeration) searchHooks(name, PRE_RESOURCES);
		} catch (ClassNotFoundException e) {
			// will not happen
		} catch (FileNotFoundException e) {
			return null;
		}
		if (result != null)
			return result;
		// start at step 3 because of the comment above about ClassLoader#getResources
		// 3) search the imported packages
		PackageSource source = findImportedSource(pkgName, null);
		if (source != null)
			// 3) found import source terminate search at the source
			return source.getResources(name);
		// 4) search the required bundles
		source = findRequiredSource(pkgName, null);
		if (source != null)
			// 4) attempt to load from source but continue on failure
			result = source.getResources(name);

		// 5) search the local bundle
		// compound the required source results with the local ones
		Enumeration localResults = findLocalResources(name);
		result = compoundEnumerations(result, localResults);
		// 6) attempt to find a dynamic import source; only do this if a required source was not found
		if (result == null && source == null) {
			source = findDynamicSource(pkgName);
			if (source != null)
				return source.getResources(name);
		}
		if (result == null)
			try {
				result = (Enumeration) searchHooks(name, POST_RESOURCES);
			} catch (ClassNotFoundException e) {
				// will not happen
			} catch (FileNotFoundException e) {
				return null;
			}
		if (policy != null) {
			Enumeration buddyResult = policy.doBuddyResourcesLoading(name);
			result = compoundEnumerations(result, buddyResult);
		}
		return result;
	}

	/*
	 * This method is used by Bundle.getResources to do proper parent delegation.
	 */
	public Enumeration getResources(String name) throws IOException {
		if ((name.length() > 1) && (name.charAt(0) == '/')) /* if name has a leading slash */
			name = name.substring(1); /* remove leading slash before search */
		String pkgName = getResourcePackageName(name);
		// follow the OSGi delegation model
		// First check the parent classloader for system resources, if it is a java resource.
		Enumeration result = null;
		if (pkgName.startsWith(JAVA_PACKAGE) || bundle.getFramework().isBootDelegationPackage(pkgName)) {
			// 1) if startsWith "java." delegate to parent and terminate search
			// 2) if part of the bootdelegation list then delegate to parent and continue of failure
			ClassLoader parentCL = getParentClassLoader();
			result = parentCL == null ? null : parentCL.getResources(name);
			if (pkgName.startsWith(JAVA_PACKAGE))
				return result;
		}
		return compoundEnumerations(result, findResources(name));
	}

	public static Enumeration compoundEnumerations(Enumeration list1, Enumeration list2) {
		if (list2 == null || !list2.hasMoreElements())
			return list1;
		if (list1 == null || !list1.hasMoreElements())
			return list2;
		Vector compoundResults = new Vector();
		while (list1.hasMoreElements())
			compoundResults.add(list1.nextElement());
		while (list2.hasMoreElements()) {
			Object item = list2.nextElement();
			if (!compoundResults.contains(item)) //don't add duplicates
				compoundResults.add(item);
		}
		return compoundResults.elements();
	}

	/**
	 * Finds a resource local to this bundle.  Only the classloader for this bundle is searched.
	 * @param name The name of the resource to find.
	 * @return The URL to the resource or null if the resource is not found.
	 */
	URL findLocalResource(final String name) {
		return createClassLoader().findLocalResource(name);
	}

	/**
	 * Returns an Enumeration of URLs representing all the resources with
	 * the given name. Only the classloader for this bundle is searched.
	 *
	 * @param  name the resource name
	 * @return an Enumeration of URLs for the resources
	 */
	Enumeration findLocalResources(String name) {
		return createClassLoader().findLocalResources(name);
	}

	/**
	 * Returns the absolute path name of a native library.
	 *
	 * @param      name   the library name
	 * @return     the absolute path of the native library or null if not found
	 */
	public String findLibrary(final String name) {
		if (System.getSecurityManager() == null)
			return findLocalLibrary(name);
		return (String) AccessController.doPrivileged(new PrivilegedAction() {
			public Object run() {
				return findLocalLibrary(name);
			}
		});
	}

	final String findLocalLibrary(final String name) {
		String result = null;
		try {
			result = (String) searchHooks(name, PRE_LIBRARY);
		} catch (FileNotFoundException e) {
			return null;
		} catch (ClassNotFoundException e) {
			// will not happen
		}
		if (result != null)
			return result;
		result = bundle.getBundleData().findLibrary(name);
		if (result != null)
			return result;

		// look in fragments imports ...
		BundleFragment[] fragments = bundle.getFragments();
		if (fragments != null)
			for (int i = 0; i < fragments.length; i++) {
				result = fragments[i].getBundleData().findLibrary(name);
				if (result != null)
					return result;
			}
		try {
			return (String) searchHooks(name, POST_LIBRARY);
		} catch (FileNotFoundException e) {
			return null; // this is not necessary; but being consistent in case another step is added below
		} catch (ClassNotFoundException e) {
			// will not happen
		}
		return null;
	}

	/*
	 * Return the bundle we are associated with.
	 */
	public final AbstractBundle getBundle() {
		return bundle;
	}

	private BundleClassLoader createBCLPrevileged(final BundleProtectionDomain pd, final String[] cp) {
		// Create the classloader as previleged code if security manager is present.
		if (System.getSecurityManager() == null)
			return createBCL(pd, cp);

		return (BundleClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
			public Object run() {
				return createBCL(pd, cp);
			}
		});

	}

	BundleClassLoader createBCL(final BundleProtectionDomain pd, final String[] cp) {
		BundleClassLoader bcl = bundle.getBundleData().createClassLoader(BundleLoader.this, pd, cp);
		// attach existing fragments to classloader
		BundleFragment[] fragments = bundle.getFragments();
		if (fragments != null)
			for (int i = 0; i < fragments.length; i++) {
				try {
					bcl.attachFragment(fragments[i].getBundleData(), fragments[i].getProtectionDomain(), fragments[i].getBundleData().getClassPath());
				} catch (BundleException be) {
					bundle.getFramework().publishFrameworkEvent(FrameworkEvent.ERROR, bundle, be);
				}
			}

		// finish the initialization of the classloader.
		bcl.initialize();
		return bcl;
	}

	/**
	 * Return a string representation of this loader.
	 * @return String
	 */
	public final String toString() {
		BundleData result = bundle.getBundleData();
		return result == null ? "BundleLoader.bundledata == null!" : result.toString(); //$NON-NLS-1$
	}

	/**
	 * Return true if the target package name matches
	 * a name in the DynamicImport-Package manifest header.
	 *
	 * @param pkgname The name of the requested class' package.
	 * @return true if the package should be imported.
	 */
	private final synchronized boolean isDynamicallyImported(String pkgname) {
		if (this instanceof SystemBundleLoader)
			return false; // system bundle cannot dynamically import
		// must check for startsWith("java.") to satisfy R3 section 4.7.2
		if (pkgname.startsWith("java.")) //$NON-NLS-1$
			return true;

		/* quick shortcut check */
		if ((loaderFlags & FLAG_HASDYNAMICIMPORTS) == 0)
			return false;

		/* "*" shortcut */
		if ((loaderFlags & FLAG_HASDYNAMICEIMPORTALL) != 0)
			return true;

		/* match against specific names */
		if (dynamicImportPackages != null)
			for (int i = 0; i < dynamicImportPackages.length; i++)
				if (pkgname.equals(dynamicImportPackages[i]))
					return true;

		/* match against names with trailing wildcards */
		if (dynamicImportPackageStems != null)
			for (int i = 0; i < dynamicImportPackageStems.length; i++)
				if (pkgname.startsWith(dynamicImportPackageStems[i]))
					return true;

		return false;
	}

	final void addExportedProvidersFor(String symbolicName, String packageName, ArrayList result, KeyedHashSet visited) {
		if (!visited.add(bundle))
			return;

		// See if we locally provide the package.
		PackageSource local = null;
		if (isExportedPackage(packageName))
			local = proxy.getPackageSource(packageName);
		else if (isSubstitutedExport(packageName)) {
			result.add(findImportedSource(packageName, visited));
			return; // should not continue to required bundles in this case
		}
		// Must search required bundles that are exported first.
		if (requiredBundles != null) {
			int size = reexportTable == null ? 0 : reexportTable.length;
			int reexportIndex = 0;
			for (int i = 0; i < requiredBundles.length; i++) {
				if (local != null) {
					// always add required bundles first if we locally provide the package
					// This allows a bundle to provide a package from a required bundle without 
					// re-exporting the whole required bundle.
					requiredBundles[i].getBundleLoader().addExportedProvidersFor(symbolicName, packageName, result, visited);
				} else if (reexportIndex < size && reexportTable[reexportIndex] == i) {
					reexportIndex++;
					requiredBundles[i].getBundleLoader().addExportedProvidersFor(symbolicName, packageName, result, visited);
				}
			}
		}

		// now add the locally provided package.
		if (local != null && local.isFriend(symbolicName))
			result.add(local);
	}

	final boolean isExportedPackage(String name) {
		return exportedPackages.contains(name);
	}

	final boolean isSubstitutedExport(String name) {
		return substitutedPackages == null ? false : substitutedPackages.contains(name);
	}

	private void addDynamicImportPackage(ImportPackageSpecification[] packages) {
		if (packages == null)
			return;
		ArrayList dynamicImports = new ArrayList(packages.length);
		for (int i = 0; i < packages.length; i++)
			if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(packages[i].getDirective(Constants.RESOLUTION_DIRECTIVE)))
				dynamicImports.add(packages[i].getName());
		if (dynamicImports.size() > 0)
			addDynamicImportPackage((String[]) dynamicImports.toArray(new String[dynamicImports.size()]));
	}

	/**
	 * Adds a list of DynamicImport-Package manifest elements to the dynamic
	 * import tables of this BundleLoader.  Duplicate packages are checked and
	 * not added again.  This method is not thread safe.  Callers should ensure
	 * synchronization when calling this method.
	 * @param packages the DynamicImport-Package elements to add.
	 */
	private void addDynamicImportPackage(String[] packages) {
		if (packages == null)
			return;

		loaderFlags |= FLAG_HASDYNAMICIMPORTS;
		int size = packages.length;
		ArrayList stems;
		if (dynamicImportPackageStems == null) {
			stems = new ArrayList(size);
		} else {
			stems = new ArrayList(size + dynamicImportPackageStems.length);
			for (int i = 0; i < dynamicImportPackageStems.length; i++) {
				stems.add(dynamicImportPackageStems[i]);
			}
		}

		ArrayList names;
		if (dynamicImportPackages == null) {
			names = new ArrayList(size);
		} else {
			names = new ArrayList(size + dynamicImportPackages.length);
			for (int i = 0; i < dynamicImportPackages.length; i++) {
				names.add(dynamicImportPackages[i]);
			}
		}

		for (int i = 0; i < size; i++) {
			String name = packages[i];
			if (isDynamicallyImported(name))
				continue;
			if (name.equals("*")) { /* shortcut *///$NON-NLS-1$
				loaderFlags |= FLAG_HASDYNAMICEIMPORTALL;
				return;
			}

			if (name.endsWith(".*")) //$NON-NLS-1$
				stems.add(name.substring(0, name.length() - 1));
			else
				names.add(name);
		}

		size = stems.size();
		if (size > 0)
			dynamicImportPackageStems = (String[]) stems.toArray(new String[size]);

		size = names.size();
		if (size > 0)
			dynamicImportPackages = (String[]) names.toArray(new String[size]);
	}

	/**
	 * Adds a list of DynamicImport-Package manifest elements to the dynamic
	 * import tables of this BundleLoader.  Duplicate packages are checked and
	 * not added again.
	 * @param packages the DynamicImport-Package elements to add.
	 */
	public final synchronized void addDynamicImportPackage(ManifestElement[] packages) {
		if (packages == null)
			return;
		ArrayList dynamicImports = new ArrayList(packages.length);
		for (int i = 0; i < packages.length; i++)
			dynamicImports.add(packages[i].getValue());
		if (dynamicImports.size() > 0)
			addDynamicImportPackage((String[]) dynamicImports.toArray(new String[dynamicImports.size()]));
	}

	synchronized public void attachFragment(BundleFragment fragment) throws BundleException {
		ExportPackageDescription[] exports = proxy.getBundleDescription().getSelectedExports();
		if (classloader == null) {
			initializeExports(exports, exportedPackages);
			return;
		}
		String[] classpath = fragment.getBundleData().getClassPath();
		if (classpath != null)
			classloader.attachFragment(fragment.getBundleData(), fragment.getProtectionDomain(), classpath);
		initializeExports(exports, exportedPackages);
	}

	/*
	 * Finds a packagesource that is either imported or required from another bundle.
	 * This will not include an local package source
	 */
	private PackageSource findSource(String pkgName) {
		if (pkgName == null)
			return null;
		PackageSource result = findImportedSource(pkgName, null);
		if (result != null)
			return result;
		// Note that dynamic imports are not checked to avoid aggressive wiring (bug 105779)  
		return findRequiredSource(pkgName, null);
	}

	private PackageSource findImportedSource(String pkgName, KeyedHashSet visited) {
		KeyedHashSet imports = getImportedSources(visited);
		if (imports == null)
			return null;
		synchronized (imports) {
			return (PackageSource) imports.getByKey(pkgName);
		}
	}

	private PackageSource findDynamicSource(String pkgName) {
		if (isDynamicallyImported(pkgName)) {
			ExportPackageDescription exportPackage = bundle.getFramework().getAdaptor().getState().linkDynamicImport(proxy.getBundleDescription(), pkgName);
			if (exportPackage != null) {
				PackageSource source = createExportPackageSource(exportPackage, null);
				synchronized (this) {
					if (importedSources == null)
						importedSources = new KeyedHashSet(false);
				}
				synchronized (importedSources) {
					importedSources.add(source);
				}
				return source;
			}
		}
		return null;
	}

	private PackageSource findRequiredSource(String pkgName, KeyedHashSet visited) {
		if (requiredBundles == null)
			return null;
		synchronized (requiredSources) {
			PackageSource result = (PackageSource) requiredSources.getByKey(pkgName);
			if (result != null)
				return result.isNullSource() ? null : result;
		}
		if (visited == null)
			visited = new KeyedHashSet(false);
		visited.add(bundle); // always add ourselves so we do not recurse back to ourselves
		ArrayList result = new ArrayList(3);
		for (int i = 0; i < requiredBundles.length; i++) {
			BundleLoader requiredLoader = requiredBundles[i].getBundleLoader();
			requiredLoader.addExportedProvidersFor(proxy.getSymbolicName(), pkgName, result, visited);
		}
		// found some so cache the result for next time and return
		PackageSource source;
		if (result.size() == 0) {
			// did not find it in our required bundles lets record the failure
			// so we do not have to do the search again for this package.
			source = NullPackageSource.getNullPackageSource(pkgName);
		} else if (result.size() == 1) {
			// if there is just one source, remember just the single source 
			source = (PackageSource) result.get(0);
		} else {
			// if there was more than one source, build a multisource and cache that.
			PackageSource[] srcs = (PackageSource[]) result.toArray(new PackageSource[result.size()]);
			source = createMultiSource(pkgName, srcs);
		}
		synchronized (requiredSources) {
			requiredSources.add(source);
		}
		return source.isNullSource() ? null : source;
	}

	/*
	 * Gets the package source for the pkgName.  This will include the local package source
	 * if the bundle exports the package.  This is used to compare the PackageSource of a 
	 * package from two different bundles.
	 */
	public final PackageSource getPackageSource(String pkgName) {
		PackageSource result = findSource(pkgName);
		if (!isExportedPackage(pkgName))
			return result;
		// if the package is exported then we need to get the local source
		PackageSource localSource = proxy.getPackageSource(pkgName);
		if (result == null)
			return localSource;
		if (localSource == null)
			return result;
		return createMultiSource(pkgName, new PackageSource[] {result, localSource});
	}

	private ClassLoader getParentPrivileged(final BundleClassLoader bcl) {
		if (System.getSecurityManager() == null)
			return bcl.getParent();

		return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
			public Object run() {
				return bcl.getParent();
			}
		});
	}

	static final class ClassContext extends SecurityManager {
		// need to make this method public
		public Class[] getClassContext() {
			return super.getClassContext();
		}
	}

	/* 
	 * see bug 121737
	 * To ensure that we do not enter a deadly embrace between classloader cycles
	 * we attempt to obtain a global lock before do normal osgi delegation.
	 * This approach ensures that only one thread has a classloader locked at a time
	 */
	private static void lock(Object loader) {
		Thread currentThread = Thread.currentThread();
		boolean interrupted = false;
		synchronized (loader) {
			if (tryLock(currentThread, loader))
				return; // this thread has the lock

			do {
				try {
					// we wait on the loader object here to release its lock incase we have it.
					// we do not way to wait while holding this lock because that will cause deadlock
					loader.wait();
				} catch (InterruptedException e) {
					interrupted = true;
					// we still want to try again
				}
			} while (!tryLock(currentThread));
		}
		if (interrupted)
			currentThread.interrupt();
	}

	/*
	 * returns true if this thread can obtain the global lock or already has the lock;
	 * otherwise this loader and thread are added to the waitingList
	 */
	private synchronized static boolean tryLock(Thread currentThread, Object loader) {
		if (lockThread == currentThread) {
			lockCount++;
			return true;
		}
		if (lockThread == null) {
			lockCount++;
			lockThread = currentThread;
			return true;
		}
		waitingList.add(new Object[] {currentThread, loader});
		return false;
	}

	/*
	 * returns true if this thread already has the global lock
	 */
	private synchronized static boolean tryLock(Thread currentThread) {
		if (lockThread == currentThread) {
			lockCount++;
			return true;
		}
		return false;
	}

	/*
	 * unlocks the global lock and notifies the first waiting thread that they
	 * now have the lock
	 */
	private static void unlock() {
		Thread waitingThread = null;
		Object loader = null;
		synchronized (BundleLoader.class) {
			lockCount--;
			if (lockCount != 0)
				return;

			if (waitingList.isEmpty()) {
				lockThread = null;
				return;
			}

			Object[] waiting = (Object[]) waitingList.get(0);
			waitingThread = (Thread) waiting[0];
			loader = waiting[1];
		}
		synchronized (loader) {
			synchronized (BundleLoader.class) {
				lockThread = waitingThread;
				waitingList.remove(0);
				loader.notifyAll();
			}
		}
	}

	static public void closeBundleLoader(BundleLoaderProxy proxy) {
		if (proxy == null)
			return;
		// First close the BundleLoader
		BundleLoader loader = proxy.getBasicBundleLoader();
		if (loader != null)
			loader.close();
		proxy.setStale();
		// if proxy is not null then make sure to unset user object
		// associated with the proxy in the state
		BundleDescription description = proxy.getBundleDescription();
		description.setUserObject(null);
	}
}
