/******************************************************************************
 * Copyright (c) 2006, 2010 VMware Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution. 
 * The Eclipse Public License is available at 
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
 * is available at http://www.opensource.org/licenses/apache2.0.php.
 * You may elect to redistribute this code under either of these licenses. 
 * 
 * Contributors:
 *   VMware Inc.
 *****************************************************************************/

package org.eclipse.gemini.blueprint.test;

import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import org.eclipse.gemini.blueprint.test.internal.util.DependencyVisitor;
import org.eclipse.gemini.blueprint.test.internal.util.jar.JarCreator;
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
import org.objectweb.asm.ClassReader;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * Enhanced subclass of {@link AbstractDependencyManagerTests} that facilitates
 * OSGi testing by creating at runtime, on the fly, a jar using the indicated
 * manifest and resource patterns (by default all files found under the root
 * path).
 * 
 * <p/>The test class can automatically determine the imports required by the
 * test, create the OSGi bundle manifest and pack the test and its resources in
 * a jar that can be installed inside an OSGi platform.
 * 
 * <p/>Additionally, a valid OSGi manifest is automatically created for the
 * resulting test if the user does not provide one. The classes present in the
 * archive are analyzed and based on their byte-code, the required
 * <code>Import-Package</code> entries (for packages not found in the bundle)
 * are created.
 * 
 * Please see the reference documentation for an in-depth explanation and usage
 * examples.
 * 
 * <p/>Note that in more complex scenarios, dedicated packaging tools (such as
 * ant scripts or maven2) should be used.
 * 
 * <p/>It is recommend to extend {@link AbstractConfigurableBundleCreatorTests}
 * rather then this class as the former offers sensible defaults.
 * 
 * @author Costin Leau
 * 
 */
public abstract class AbstractOnTheFlyBundleCreatorTests extends AbstractDependencyManagerTests {

	private static final String META_INF_JAR_LOCATION = "/META-INF/MANIFEST.MF";

	JarCreator jarCreator;

	/** field used for caching jar content */
	private Map jarEntries;
	/** discovered manifest */
	private Manifest manifest;


	public AbstractOnTheFlyBundleCreatorTests() {
		initializeJarCreator();
	}

	public AbstractOnTheFlyBundleCreatorTests(String testName) {
		super(testName);
		initializeJarCreator();
	}

	private void initializeJarCreator() {
		AccessController.doPrivileged(new PrivilegedAction() {

			public Object run() {
				jarCreator = new JarCreator();
				return null;
			}
		});
	}

	/**
	 * Returns the root path used for locating the resources that will be packed
	 * in the test bundle (the root path does not become part of the jar).
	 *
     * <p/>By default, the current threads context ClassLoader is used to locate
     * the root of the classpath. Because unit tests will either be run from Maven
     * or an IDE this will resolve a test classes directory of sorts.
     *
     * <p/>For example when invoked from Maven <code>"file:./target/test-classes"</code>
     * will be resolved and used.
     *
	 * @return root path given as a String
	 */
	protected String getRootPath() {
		return Thread.currentThread().getContextClassLoader().getResource(".").toString();
	}

	/**
	 * Returns the patterns used for identifying the resources added to the jar.
	 * The patterns are added to the root path when performing the search. By
	 * default, the pattern is <code>*&#42;/*</code>.
	 * 
	 * <p/>In large test environments, performance can be improved by limiting
	 * the resource added to the bundle by selecting only certain packages or
	 * classes. This results in a small test bundle which is faster to create,
	 * deploy and install.
	 * 
	 * @return the patterns identifying the resources added to the jar
	 */
	protected String[] getBundleContentPattern() {
		return new String[] { JarCreator.EVERYTHING_PATTERN };
	}

	/**
	 * Returns the location (in Spring resource style) of the manifest location
	 * to be used. By default <code>null</code> is returned, indicating that
	 * the manifest should be picked up from the bundle content (if it's
	 * available) or be automatically created based on the test class imports.
	 * 
	 * @return the manifest location
	 * @see #getManifest()
	 * @see #createDefaultManifest()
	 */
	protected String getManifestLocation() {
		return null;
	}

	/**
	 * Returns the current test bundle manifest. The method tries to read the
	 * manifest from the given location; in case the location is
	 * <code>null</code> (default), it will search for
	 * <code>META-INF/MANIFEST.MF</code> file in jar content (as specified
	 * through the patterns) and, if it cannot find the file,
	 * <em>automatically</em> create a <code>Manifest</code> object
	 * containing default entries.
	 * 
	 * <p/> Subclasses can override this method to enhance the returned
	 * Manifest.
	 * 
	 * @return Manifest used for this test suite.
	 * 
	 * @see #createDefaultManifest()
	 */
	protected Manifest getManifest() {
		// return cached manifest
		if (manifest != null)
			return manifest;

		String manifestLocation = getManifestLocation();
		if (StringUtils.hasText(manifestLocation)) {
			logger.info("Using Manifest from specified location=[" + getManifestLocation() + "]");
			DefaultResourceLoader loader = new DefaultResourceLoader();
			manifest = createManifestFrom(loader.getResource(manifestLocation));
		}

		else {
			// set root path
			jarCreator.setRootPath(getRootPath());
			// add the content pattern
			jarCreator.setContentPattern(getBundleContentPattern());

			// see if the manifest already exists in the classpath
			// to resolve the patterns
			jarEntries = jarCreator.resolveContent();

			for (Iterator iterator = jarEntries.entrySet().iterator(); iterator.hasNext();) {
				Map.Entry entry = (Map.Entry) iterator.next();
				if (META_INF_JAR_LOCATION.equals(entry.getKey())) {
					logger.info("Using Manifest from the test bundle content=[/META-INF/MANIFEST.MF]");
					manifest = createManifestFrom((Resource) entry.getValue());
				}
			}
			// fallback to default manifest creation

			if (manifest == null) {
				logger.info("Automatically creating Manifest for the test bundle");
				manifest = createDefaultManifest();
			}
		}

		return manifest;
	}

	/**
	 * Indicates if the automatic manifest creation should consider only the
	 * test class (<code>true</code>) or all classes included in the test
	 * bundle(<code>false</code>). The latter should be used when the test
	 * bundle contains additional classes that help with the test case.
	 * 
	 * <p/> By default, this method returns <code>true</code>, meaning that
	 * only the test class will be searched for dependencies.
	 * 
	 * @return true if only the test hierarchy is searched for dependencies or
	 *         false if all classes discovered in the test archive need to be
	 *         parsed.
	 */
	protected boolean createManifestOnlyFromTestClass() {
		return true;
	}

	private Manifest createManifestFrom(Resource resource) {
		Assert.notNull(resource, "unable to create manifest for empty resources");
		try {
			return new Manifest(resource.getInputStream());
		}
		catch (IOException ex) {
			throw (RuntimeException) new IllegalArgumentException("cannot create manifest from " + resource).initCause(ex);
		}
	}

	/**
	 * Creates the default manifest in case none if found on the disk. By
	 * default, the imports are synthetised based on the test class bytecode.
	 * 
	 * @return default manifest for the jar created on the fly
	 */
	protected Manifest createDefaultManifest() {
		Manifest manifest = new Manifest();
		Attributes attrs = manifest.getMainAttributes();

		// manifest versions
		attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
		attrs.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");

		String description = getName() + "-" + getClass().getName();
		// name/description
		attrs.putValue(Constants.BUNDLE_NAME, "TestBundle-" + description);
		attrs.putValue(Constants.BUNDLE_SYMBOLICNAME, "TestBundle-" + description);
		attrs.putValue(Constants.BUNDLE_DESCRIPTION, "on-the-fly test bundle");

		// activator
		attrs.putValue(Constants.BUNDLE_ACTIVATOR, JUnitTestActivator.class.getName());

		// add Import-Package entry
		addImportPackage(manifest);

		if (logger.isDebugEnabled())
			logger.debug("Created manifest:" + manifest.getMainAttributes().entrySet());
		return manifest;
	}

	private void addImportPackage(Manifest manifest) {
		String[] rawImports = determineImports();

		boolean trace = logger.isTraceEnabled();

		if (trace)
			logger.trace("Discovered raw imports " + ObjectUtils.nullSafeToString(rawImports));

		Collection specialImportsOut = eliminateSpecialPackages(rawImports);
		Collection imports = eliminatePackagesAvailableInTheJar(specialImportsOut);

		if (trace)
			logger.trace("Filtered imports are " + imports);

		manifest.getMainAttributes().putValue(Constants.IMPORT_PACKAGE,
			StringUtils.collectionToCommaDelimitedString(imports));
	}

	/**
	 * Eliminate 'special' packages (java.*, test framework internal and the
	 * class declaring package)
	 * 
	 * @param rawImports
	 * @return
	 */
	private Collection eliminateSpecialPackages(String[] rawImports) {
		String currentPckg = ClassUtils.classPackageAsResourcePath(getClass()).replace('/', '.');

		Set filteredImports = new LinkedHashSet(rawImports.length);
		Set eliminatedImports = new LinkedHashSet(4);

		for (int i = 0; i < rawImports.length; i++) {
			String pckg = rawImports[i];

			if (!(pckg.startsWith("java.") || pckg.startsWith("org.eclipse.gemini.blueprint.test.internal") || pckg.equals(currentPckg)))
				filteredImports.add(pckg);
			else
				eliminatedImports.add(pckg);
		}

		if (!eliminatedImports.isEmpty() && logger.isTraceEnabled())
			logger.trace("Eliminated special packages " + eliminatedImports);

		return filteredImports;
	}

	/**
	 * Eliminates imports for packages already included in the bundle. Works
	 * only if the jar content is known (variable 'jarEntries' set).
	 * 
	 * @param imports
	 * @return
	 */
	private Collection eliminatePackagesAvailableInTheJar(Collection imports) {
		// no jar entry present, bail out.
		if (jarEntries == null || jarEntries.isEmpty())
			return imports;

		Set filteredImports = new LinkedHashSet(imports.size());
		Collection eliminatedImports = new LinkedHashSet(2);

		Collection jarPackages = jarCreator.getContainedPackages();
		for (Iterator iterator = imports.iterator(); iterator.hasNext();) {
			String pckg = (String) iterator.next();
			if (jarPackages.contains(pckg))
				eliminatedImports.add(pckg);
			else
				filteredImports.add(pckg);
		}
		if (!eliminatedImports.isEmpty() && logger.isTraceEnabled())
			logger.trace("Eliminated packages already present in the bundle " + eliminatedImports);

		return filteredImports;
	}

	/**
	 * Determine imports for the given bundle. Based on the user settings, this
	 * method will consider only the the test hierarchy until the testing
	 * framework is found or all classes available inside the test bundle. <p/>
	 * Note that split packages are not supported.
	 * 
	 * @return
	 */
	private String[] determineImports() {

		boolean useTestClassOnly = false;

		// no jar entry present, bail out.
		if (jarEntries == null || jarEntries.isEmpty()) {
			logger.debug("No test jar content detected, generating bundle imports from the test class");
			useTestClassOnly = true;
		}

		else if (createManifestOnlyFromTestClass()) {
			logger.info("Using the test class for generating bundle imports");
			useTestClassOnly = true;
		}
		else
			logger.info("Using all classes in the jar for the generation of bundle imports");

		// className, class resource
		Map entries;

		if (useTestClassOnly) {

			entries = new LinkedHashMap(4);

			// get current class (test class that bootstraps the OSGi infrastructure)
			Class<?> clazz = getClass();
			String clazzPackage = null;
			String endPackage = AbstractOnTheFlyBundleCreatorTests.class.getPackage().getName();

			do {

				// consider inner classes as well
				List classes = new ArrayList(4);
				classes.add(clazz);
				CollectionUtils.mergeArrayIntoCollection(clazz.getDeclaredClasses(), classes);

				for (Iterator iterator = classes.iterator(); iterator.hasNext();) {
					Class<?> classToInspect = (Class) iterator.next();

					Package pkg = classToInspect.getPackage();
					if (pkg != null) {
						clazzPackage = pkg.getName();
						String classFile = ClassUtils.getClassFileName(classToInspect);
						entries.put(classToInspect.getName().replace('.', '/').concat(ClassUtils.CLASS_FILE_SUFFIX),
							new InputStreamResource(classToInspect.getResourceAsStream(classFile)));
					}
					// handle default package
					else {
						logger.warn("Could not find package for class " + classToInspect + "; ignoring...");
					}
				}

				clazz = clazz.getSuperclass();

			} while (!endPackage.equals(clazzPackage));
		}
		else
			entries = jarEntries;

		return determineImportsFor(entries);

	}

	private String[] determineImportsFor(Map entries) {
		// get contained packages to do matching on the test hierarchy
		Collection containedPackages = jarCreator.getContainedPackages();
		Set cumulatedPackages = new LinkedHashSet();

		// make sure the collection package is valid
		boolean validPackageCollection = !containedPackages.isEmpty();

		boolean trace = logger.isTraceEnabled();

		for (Iterator iterator = entries.entrySet().iterator(); iterator.hasNext();) {
			Map.Entry entry = (Map.Entry) iterator.next();
			String resourceName = (String) entry.getKey();

			// filter out the test hierarchy
			if (resourceName.endsWith(ClassUtils.CLASS_FILE_SUFFIX)) {
				if (trace)
					logger.trace("Analyze imports for test bundle resource " + resourceName);
				String classFileName = StringUtils.getFilename(resourceName);
				String className = classFileName.substring(0, classFileName.length()
						- ClassUtils.CLASS_FILE_SUFFIX.length());
				String classPkg = resourceName.substring(0, resourceName.length() - classFileName.length()).replace(
					'/', '.');

				if (classPkg.startsWith("."))
					classPkg = classPkg.substring(1);

				if (classPkg.endsWith("."))
					classPkg = classPkg.substring(0, classPkg.length() - 1);

				// if we don't have the package, add it
				if (validPackageCollection && StringUtils.hasText(classPkg) && !containedPackages.contains(classPkg)) {
					logger.trace("Package [" + classPkg + "] is NOT part of the test archive; adding an import for it");
					cumulatedPackages.add(classPkg);
				}

				// otherwise parse the class byte-code
				else {
					if (trace)
						logger.trace("Package [" + classPkg + "] is part of the test archive; parsing " + className
								+ " bytecode to determine imports...");
					cumulatedPackages.addAll(determineImportsForClass(className, (Resource) entry.getValue()));
				}
			}
		}

		return (String[]) cumulatedPackages.toArray(new String[cumulatedPackages.size()]);
	}

	/**
	 * Determine imports for a class given as a String resource. This method
	 * doesn't do any search for the enclosing/inner classes as it considers
	 * that these should be handled at a higher level.
	 * 
	 * The returned set contains the packages in string format (i.e. java.io)
	 * 
	 * @param className
	 * @param resource
	 * @return
	 */
	private Set determineImportsForClass(String className, Resource resource) {
		Assert.notNull(resource, "a not-null class is required");
		DependencyVisitor visitor = new DependencyVisitor();

		boolean trace = logger.isTraceEnabled();

		ClassReader reader;

		try {
			if (trace)
				logger.trace("Visiting class " + className);
			reader = new ClassReader(resource.getInputStream());
		}
		catch (Exception ex) {
			throw (RuntimeException) new IllegalArgumentException("Cannot read class " + className).initCause(ex);
		}
		reader.accept(visitor, false);

		// convert from / to . format
		Set originalPackages = visitor.getPackages();
		Set pkgs = new LinkedHashSet(originalPackages.size());

		for (Iterator iterator = originalPackages.iterator(); iterator.hasNext();) {
			String pkg = (String) iterator.next();
			pkgs.add(pkg.replace('/', '.'));
		}
		return pkgs;
	}

	protected void postProcessBundleContext(BundleContext context) throws Exception {
		logger.debug("Post processing: creating test bundle");

		Resource jar;

		Manifest mf = getManifest();

		// if the jar content hasn't been discovered yet (while creating the manifest)
		// do so now
		if (jarEntries == null) {
			// set root path
			jarCreator.setRootPath(getRootPath());
			// add the content pattern
			jarCreator.setContentPattern(getBundleContentPattern());

			// use jar creator for pattern discovery
			jar = jarCreator.createJar(mf);
		}

		// otherwise use the cached resources
		else {
			jar = jarCreator.createJar(mf, jarEntries);
		}

		try {
			installAndStartBundle(context, jar);
		}
		catch (Exception e) {
			IllegalStateException ise = new IllegalStateException(
				"Unable to dynamically start generated unit test bundle");
			ise.initCause(e);
			throw ise;
		}

		// now do the delegation
		super.postProcessBundleContext(context);
	}

	private void installAndStartBundle(BundleContext context, Resource resource) throws Exception {
		// install & start
		Bundle bundle = context.installBundle("[onTheFly-test-bundle]" + ClassUtils.getShortName(getClass()) + "["
				+ hashCode() + "]", resource.getInputStream());

		String bundleString = OsgiStringUtils.nullSafeNameAndSymName(bundle);
		boolean debug = logger.isDebugEnabled();

		if (debug)
			logger.debug("Test bundle [" + bundleString + "] successfully installed");
		bundle.start();
		if (debug)
			logger.debug("Test bundle [" + bundleString + "] successfully started");
	}

}
