/*******************************************************************************
 * Copyright (c) 2003,2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.core.runtime.adaptor;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.*;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import org.eclipse.osgi.framework.adaptor.BundleData;
import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
import org.eclipse.osgi.framework.adaptor.core.*;
import org.eclipse.osgi.framework.internal.core.AbstractBundle;
import org.eclipse.osgi.framework.internal.core.Msg;
import org.eclipse.osgi.framework.internal.defaultadaptor.DefaultClassLoader;
import org.eclipse.osgi.framework.internal.defaultadaptor.DevClassPathHelper;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.framework.stats.ClassloaderStats;
import org.eclipse.osgi.framework.stats.ResourceBundleStats;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.*;

public class EclipseClassLoader extends DefaultClassLoader {
	private static String[] NL_JAR_VARIANTS = buildNLJarVariants(System.getProperties().getProperty("osgi.nl")); //$NON-NLS-1$
	// from Eclipse-AutoStart element value
	private boolean autoStart;
	// from Eclipse-AutoStart's "exceptions" attribute
	private String[] exceptions;

	public EclipseClassLoader(ClassLoaderDelegate delegate, ProtectionDomain domain, String[] classpath, ClassLoader parent, BundleData bundleData) {
		super(delegate, domain, classpath, parent, (org.eclipse.osgi.framework.internal.defaultadaptor.DefaultBundleData) bundleData);
		parseAutoStart(bundleData);
	}

	private void parseAutoStart(BundleData bundleData) {
		try {
			String automationHeader = (String) bundleData.getManifest().get(EclipseAdaptorConstants.ECLIPSE_AUTOSTART);
			ManifestElement[] allElements = ManifestElement.parseHeader(EclipseAdaptorConstants.ECLIPSE_AUTOSTART, automationHeader);
			//Eclipse-AutoStart not found... look for the Legacy header instead		//TODO This is old code, this can be removed
			if (allElements == null) {
				autoStart = "true".equalsIgnoreCase((String) bundleData.getManifest().get(EclipseAdaptorConstants.LEGACY)); //$NON-NLS-1$
				return;
			}
			// the single value for this element should be true|false
			autoStart = "true".equalsIgnoreCase(allElements[0].getValue()); //$NON-NLS-1$
			// look for any exceptions (the attribute) to the autoActivate setting
			String exceptionsValue = allElements[0].getAttribute(EclipseAdaptorConstants.EXCEPTIONS_ATTRIBUTE);
			if (exceptionsValue != null) {
				StringTokenizer tokenizer = new StringTokenizer(exceptionsValue, ","); //$NON-NLS-1$
				int numberOfTokens = tokenizer.countTokens();
				exceptions = new String[numberOfTokens];
				for (int i = 0; i < numberOfTokens; i++) {
					exceptions[i] = tokenizer.nextToken().trim();
				}
			}
		} catch (BundleException e) {
			// just use the default settings (no auto activation)
			String message = EclipseAdaptorMsg.formatter.getString("ECLIPSE_CLASSLOADER_CANNOT_GET_HEADERS", bundleData.getLocation()); //$NON-NLS-1$
			EclipseAdaptor.getDefault().getFrameworkLog().log(new FrameworkLogEntry(EclipseAdaptorConstants.PI_ECLIPSE_OSGI, message, 0, e, null));
		}
	}

	public Class findLocalClass(String name) throws ClassNotFoundException {
		if (EclipseAdaptor.MONITOR_CLASSES) //Suport for performance analysis
			ClassloaderStats.startLoadingClass(getClassloaderId(), name);
		boolean found = true;

		try {
			AbstractBundle bundle = (AbstractBundle) hostdata.getBundle();
			// If the bundle is active, just return the class
			if (bundle.getState() == AbstractBundle.ACTIVE)
				return super.findLocalClass(name);

			//If the bundle is uninstalled, classes can still be loaded from it
			if (bundle.getState() == AbstractBundle.UNINSTALLED)
				return super.findLocalClass(name);

			//If the bundle is stopping, we don't want to reactive it but we still want to be able to load classes from it.
			if (bundle.getState() == AbstractBundle.STOPPING)
				return super.findLocalClass(name);

			// The bundle is not active and does not require activation, just return the class
			if (!shouldActivateFor(name))
				return super.findLocalClass(name);

			// The bundle is starting
			if (bundle.getState() == AbstractBundle.STARTING) {
				//If the thread trying to load the class is the one trying to activate the bundle, then return the class 
				if (bundle.testStateChanging(Thread.currentThread()) || bundle.testStateChanging(null))
					return super.findLocalClass(name);

				//If it's another thread, we wait and try again. In any case the class is returned. The difference is that an exception can be logged.
				if (!bundle.testStateChanging(Thread.currentThread())) {
					Object lock = bundle.getStateChangeLock();
					long start = System.currentTimeMillis();
					long delay = 5000;
					long timeLeft = delay;
					while (true) {
						if (bundle.testStateChanging(null))
							break;

						if (timeLeft <= 0)
							break;
						try {
							synchronized (lock) {
								lock.wait(timeLeft);
							}
						} catch (InterruptedException e) {
							//Ignore and keep waiting
						}
						timeLeft = start + delay - System.currentTimeMillis();
					}
					if (timeLeft <= 0 || bundle.getState() != AbstractBundle.ACTIVE) {
						String message = EclipseAdaptorMsg.formatter.getString("ECLIPSE_CLASSLOADER_CONCURRENT_STARTUP", new Object[] {Thread.currentThread(), name, bundle.getStateChanging().getName(), bundle.getSymbolicName() == null ? Long.toString(bundle.getBundleId()) : bundle.getSymbolicName()}); //$NON-NLS-1$
						EclipseAdaptor.getDefault().getFrameworkLog().log(new FrameworkLogEntry(EclipseAdaptorConstants.PI_ECLIPSE_OSGI, message, 0, null, null));
					}
					return super.findLocalClass(name);
				}
			}

			//The bundle must be started.
			try {
				hostdata.getBundle().start();
			} catch (BundleException e) {
				String message = EclipseAdaptorMsg.formatter.getString("ECLIPSE_CLASSLOADER_ACTIVATION", bundle.getSymbolicName(), Long.toString(bundle.getBundleId())); //$NON-NLS-1$
				EclipseAdaptor.getDefault().getFrameworkLog().log(new FrameworkLogEntry(EclipseAdaptorConstants.PI_ECLIPSE_OSGI, message, 0, e, null));
			} finally {
				return super.findLocalClass(name);
			}
		} catch (ClassNotFoundException e) {
			found = false;
			throw e;
		} finally {
			if (EclipseAdaptor.MONITOR_CLASSES)
				ClassloaderStats.endLoadingClass(getClassloaderId(), name, found);
		}
	}

	/**
	 * Determines if for loading the given class we should activate the bundle. 
	 */
	private boolean shouldActivateFor(String className) {
		//Don't reactivate on shut down
		if (EclipseAdaptor.stopping)
			return false;
		// no exceptions, it is easy to figure it out
		if (exceptions == null)
			return autoStart;
		// otherwise, we need to check if the package is in the exceptions list
		int dotPosition = className.lastIndexOf('.');
		// the class has no package name... no exceptions apply
		if (dotPosition == -1)
			return autoStart;
		String packageName = className.substring(0, dotPosition);
		// should activate if autoStart and package not in exceptions, or if !autoStart and package in exceptions
		return autoStart ^ exceptionsContained(packageName);
	}

	private boolean exceptionsContained(String packageName) {
		for (int i = 0; i < exceptions.length; i++) {
			if (exceptions[i].equals(packageName))
				return true;
		}
		return false;
	}

	/**
	 * Override defineClass to allow for package defining.
	 */
	protected Class defineClass(String name, byte[] classbytes, int off, int len, ClasspathEntry classpathEntry) throws ClassFormatError {
		// Define the package if it is not the default package.
		int lastIndex = name.lastIndexOf('.');
		if (lastIndex != -1) {
			String packageName = name.substring(0, lastIndex);
			Package pkg = getPackage(packageName);
			if (pkg == null) {
				// get info about the package from the classpath entry's manifest.
				String specTitle = null, specVersion = null, specVendor = null, implTitle = null, implVersion = null, implVendor = null;
				Manifest mf = ((EclipseClasspathEntry) classpathEntry).getManifest();
				if (mf != null) {
					Attributes mainAttributes = mf.getMainAttributes();
					String dirName = packageName.replace('.', '/') + '/';
					Attributes packageAttributes = mf.getAttributes(dirName);
					boolean noEntry = false;
					if (packageAttributes == null) {
						noEntry = true;
						packageAttributes = mainAttributes;
					}
					specTitle = packageAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE);
					if (specTitle == null && !noEntry)
						specTitle = mainAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE);
					specVersion = packageAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION);
					if (specVersion == null && !noEntry)
						specVersion = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION);
					specVendor = packageAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR);
					if (specVendor == null && !noEntry)
						specVendor = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VENDOR);
					implTitle = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
					if (implTitle == null && !noEntry)
						implTitle = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
					implVersion = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
					if (implVersion == null && !noEntry)
						implVersion = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
					implVendor = packageAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
					if (implVendor == null && !noEntry)
						implVendor = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
				}
				// The package is not defined yet define it before we define the class.
				// TODO still need to seal packages.
				definePackage(packageName, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, null);
			}
		}
		return super.defineClass(name, classbytes, off, len, classpathEntry);
	}

	private String getClassloaderId() {
		return hostdata.getBundle().getSymbolicName();
	}

	public URL getResouce(String name) {
		URL result = super.getResource(name);
		if (EclipseAdaptor.MONITOR_RESOURCE_BUNDLES) {
			if (result != null && name.endsWith(".properties")) { //$NON-NLS-1$
				ClassloaderStats.loadedBundle(getClassloaderId(), new ResourceBundleStats(getClassloaderId(), name, result));
			}
		}
		return result;
	}

	protected void findClassPathEntry(ArrayList result, String entry, AbstractBundleData bundledata, ProtectionDomain domain) {
		String var = hasPrefix(entry);
		if (var == null) {
			super.findClassPathEntry(result, entry, bundledata, domain);
			return;
		}
		if (var.equals("ws")) { //$NON-NLS-1$
			super.findClassPathEntry(result, "ws/" + System.getProperties().getProperty("osgi.ws") + entry.substring(4), bundledata, domain); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			return;
		}
		if (var.equals("os")) { //$NON-NLS-1$
			super.findClassPathEntry(result, "os/" + System.getProperties().getProperty("osgi.os") + entry.substring(4), bundledata, domain); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			return;
		}
		if (var.equals("nl")) { //$NON-NLS-1$
			entry = entry.substring(4);
			for (int i = 0; i < NL_JAR_VARIANTS.length; i++) {
				if (addClassPathEntry(result, "nl/" + NL_JAR_VARIANTS[i] + entry, bundledata, domain)) //$NON-NLS-1$ //$NON-NLS-2$
					return;
			}
			// is we are not in development mode, post some framework errors.
			if (!DevClassPathHelper.inDevelopmentMode()) {
				BundleException be = new BundleException(Msg.formatter.getString("BUNDLE_CLASSPATH_ENTRY_NOT_FOUND_EXCEPTION", entry, hostdata.getLocation())); //$NON-NLS-1$
				bundledata.getAdaptor().getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundledata.getBundle(), be);
			}
		}
	}

	private static String[] buildNLJarVariants(String nl) {
		ArrayList result = new ArrayList();
		nl = nl.replace('_', '/');
		while (nl.length() > 0) {
			result.add("nl/" + nl + "/"); //$NON-NLS-1$ //$NON-NLS-2$
			int i = nl.lastIndexOf('/'); //$NON-NLS-1$
			nl = (i < 0) ? "" : nl.substring(0, i); //$NON-NLS-1$
		}
		result.add(""); //$NON-NLS-1$
		return (String[]) result.toArray(new String[result.size()]);
	}

	//return a String representing the string found between the $s
	private 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;
	}

	/**
	 * Override to create EclipseClasspathEntry objects.  EclipseClasspathEntry
	 * allows access to the manifest file for the classpath entry.
	 */
	protected ClasspathEntry createClassPathEntry(BundleFile bundlefile, ProtectionDomain domain) {
		return new EclipseClasspathEntry(bundlefile, domain);
	}

	/**
	 * A ClasspathEntry that has a manifest associated with it.
	 */
	protected class EclipseClasspathEntry extends ClasspathEntry {
		Manifest mf;
		boolean initMF = false;

		protected EclipseClasspathEntry(BundleFile bundlefile, ProtectionDomain domain) {
			super(bundlefile, domain);
		}

		public Manifest getManifest() {
			if (initMF)
				return mf;

			BundleEntry mfEntry = getBundleFile().getEntry(org.eclipse.osgi.framework.internal.core.Constants.OSGI_BUNDLE_MANIFEST);
			if (mfEntry != null)
				try {
					InputStream manIn = mfEntry.getInputStream();
					mf = new Manifest(manIn);
					manIn.close();
				} catch (IOException e) {
					// do nothing
				}
			initMF = true;
			return mf;
		}
	}
}