/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM - Initial API and implementation
 *******************************************************************************/
package org.eclipse.pde.internal.build.builder;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import org.eclipse.core.internal.boot.PlatformURLHandler;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.p2.publisher.eclipse.FeatureEntry;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.internal.build.*;
import org.eclipse.pde.internal.build.site.PDEState;
import org.osgi.framework.Filter;

public class ClasspathComputer3_0 implements IClasspathComputer, IPDEBuildConstants, IXMLConstants, IBuildPropertiesConstants {
	public class ClasspathElement {
		private final String path;
		private final String subPath;
		private String accessRules;

		/**
		 * Create a ClasspathElement object
		 * @param path
		 * @param accessRules
		 * @throws NullPointerException if path is null
		 */
		protected ClasspathElement(String path, String subPath, String accessRules) {
			if (path == null)
				throw new NullPointerException();
			this.path = path;
			this.subPath = subPath;
			this.accessRules = accessRules;
		}

		@Override
		public String toString() {
			return path;
		}

		public String getPath() {
			return path;
		}

		public String getSubPath() {
			return subPath;
		}

		public String getAccessRules() {
			return accessRules;
		}

		public String getAbsolutePath() {
			File f = new File(path);
			if (f.isAbsolute()) {
				try {
					return f.getCanonicalPath();
				} catch (IOException e) {
					return path;
				}
			}

			f = new File(modelLocation, path);
			try {
				return f.getCanonicalPath();
			} catch (IOException e) {
				return f.getPath();
			}
		}

		public void addRules(String newRule) {
			if (accessRules.equals("") || accessRules.equals(newRule)) //$NON-NLS-1$
				return;
			if (!newRule.equals("")) { //$NON-NLS-1$
				String join = accessRules.substring(0, accessRules.length() - EXCLUDE_ALL_RULE.length() - 1);
				newRule = join + newRule.substring(1);
			}
			accessRules = newRule;
			return;
		}

		/**
		 * ClasspathElement objects are equal if they have the same path.
		 * Access rules are not considered.
		 */
		@Override
		public boolean equals(Object obj) {
			if (obj instanceof ClasspathElement) {
				ClasspathElement element = (ClasspathElement) obj;
				if (!path.equals(element.getPath()))
					return false;
				if (subPath != null && subPath.equals(element.getSubPath()))
					return false;
				return true;
			}
			return false;
		}

		@Override
		public int hashCode() {
			int result = path.hashCode();
			return 13 * result + ((subPath == null) ? 0 : subPath.hashCode());
		}

	}

	private static String normalize(String path) {
		if (path == null)
			return null;
		//always use '/' as a path separator to help with comparing paths in equals
		return path.replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	private static final String EXCLUDE_ALL_RULE = "?**/*"; //$NON-NLS-1$

	private final ModelBuildScriptGenerator generator;
	private Map<String, String> visiblePackages = null;
	private Map<String, ClasspathElement> pathElements = null;
	private boolean allowBinaryCycles = false;
	private Set<Long> requiredIds = null;
	protected String modelLocation = null;

	public ClasspathComputer3_0(ModelBuildScriptGenerator modelGenerator) {
		this.generator = modelGenerator;
	}

	/**
	 * Compute the classpath for the given jar.
	 * The path returned conforms to Parent / Prerequisite / Self  
	 * 
	 * @param model the plugin containing the jar compiled
	 * @param jar the jar for which the classpath is being compiled
	 * @return String the classpath
	 * @throws CoreException
	 */
	@Override
	public List<Object> getClasspath(BundleDescription model, ModelBuildScriptGenerator.CompiledEntry jar) throws CoreException {
		List<Object> classpath = new ArrayList<>(20);
		List<BundleDescription> pluginChain = new ArrayList<>(10); //The list of plugins added to detect cycle
		modelLocation = generator.getLocation(model);
		Set<BundleDescription> addedPlugins = new HashSet<>(10); //The set of all the plugins already added to the classpath (this allows for optimization)
		pathElements = new HashMap<>();
		visiblePackages = getVisiblePackages(model);
		requiredIds = new HashSet<>();
		allowBinaryCycles = AbstractScriptGenerator.getPropertyAsBoolean(IBuildPropertiesConstants.PROPERTY_ALLOW_BINARY_CYCLES);

		//PREREQUISITE
		addPrerequisites(model, classpath, modelLocation, pluginChain, addedPlugins);

		//SELF
		addSelf(model, jar, classpath, modelLocation, pluginChain, addedPlugins);

		recordRequiredIds(model);

		return classpath;

	}

	private void recordRequiredIds(BundleDescription model) {
		Properties bundleProperties = null;
		bundleProperties = (Properties) model.getUserObject();
		if (bundleProperties == null) {
			bundleProperties = new Properties();
			model.setUserObject(bundleProperties);
		}
		StringBuffer buffer = new StringBuffer();
		for (Iterator<Long> iterator = requiredIds.iterator(); iterator.hasNext();) {
			buffer.append(iterator.next().toString());
			buffer.append(':');
		}
		bundleProperties.setProperty(PROPERTY_REQUIRED_BUNDLE_IDS, buffer.toString());
	}

	private Map<String, String> getVisiblePackages(BundleDescription model) {
		Map<String, String> packages = new HashMap<>(20);
		StateHelper helper = Platform.getPlatformAdmin().getStateHelper();
		addVisiblePackagesFromState(helper, model, packages);
		if (model.getHost() != null)
			addVisiblePackagesFromState(helper, (BundleDescription) model.getHost().getSupplier(), packages);
		return packages;
	}

	private void addVisiblePackagesFromState(StateHelper helper, BundleDescription model, Map<String, String> packages) {
		ExportPackageDescription[] exports = helper.getVisiblePackages(model);
		for (int i = 0; i < exports.length; i++) {
			BundleDescription exporter = exports[i].getExporter();
			if (exporter == null)
				continue;

			boolean discouraged = helper.getAccessCode(model, exports[i]) == StateHelper.ACCESS_DISCOURAGED;
			String pattern = exports[i].getName().replaceAll("\\.", "/") + "/*"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			String rule = (discouraged ? '~' : '+') + pattern;

			String packagesKey = exporter.getSymbolicName() + "_" + exporter.getVersion(); //$NON-NLS-1$
			String rules = packages.get(packagesKey);
			if (rules != null) {
				if (rules.indexOf(rule) == -1)
					rules = rules + File.pathSeparator + rule;
			} else {
				rules = rule;
			}

			packages.put(packagesKey, rules);
		}
	}

	/**
	 * Add the specified plugin (including its jars) and its fragments 
	 * @param plugin
	 * @param classpath
	 * @param location
	 * @throws CoreException
	 */
	private void addPlugin(BundleDescription plugin, List<Object> classpath, String location) throws CoreException {
		boolean allFragments = true;
		String patchInfo = generator.getSite(false).getRegistry().getPatchData().get(new Long(plugin.getBundleId()));
		if (patchInfo != null && plugin != generator.getModel()) {
			addFragmentsLibraries(plugin, classpath, location, false, false);
			allFragments = false;
		}

		requiredIds.add(new Long(plugin.getBundleId()));

		addRuntimeLibraries(plugin, classpath, location);
		addFragmentsLibraries(plugin, classpath, location, true, allFragments);
	}

	/**
	 * Add the runtime libraries for the specified plugin. 
	 * @param model
	 * @param classpath
	 * @param baseLocation
	 * @throws CoreException
	 */
	private void addRuntimeLibraries(BundleDescription model, List<Object> classpath, String baseLocation) throws CoreException {
		String[] libraries = getClasspathEntries(model);
		String root = generator.getLocation(model);
		IPath base = Utils.makeRelative(new Path(root), new Path(baseLocation));
		Properties modelProps = getBuildPropertiesFor(model);
		if (modelProps != AbstractScriptGenerator.MissingProperties.getInstance())
			ModelBuildScriptGenerator.specialDotProcessing(modelProps, libraries);
		for (int i = 0; i < libraries.length; i++) {
			addDevEntries(model, baseLocation, classpath, Utils.getArrayFromString(modelProps.getProperty(PROPERTY_OUTPUT_PREFIX + libraries[i])), modelProps);
			addPathAndCheck(model, base, libraries[i], modelProps, classpath);
		}
	}

	/**
	 * Add all fragments of the given plugin
	 * @param plugin
	 * @param classpath
	 * @param baseLocation
	 * @throws CoreException
	 */
	private void addFragmentsLibraries(BundleDescription plugin, List<Object> classpath, String baseLocation, boolean afterPlugin, boolean all) throws CoreException {
		// if plugin is not a plugin, it's a fragment and there is no fragment for a fragment. So we return.
		BundleDescription[] fragments = plugin.getFragments();
		if (fragments == null)
			return;

		for (int i = 0; i < fragments.length; i++) {
			if (fragments[i] == generator.getModel())
				continue;
			if (matchFilter(fragments[i]) == false)
				continue;

			requiredIds.add(new Long(fragments[i].getBundleId()));

			if (!afterPlugin && isPatchFragment(fragments[i])) {
				addPluginLibrariesToFragmentLocations(plugin, fragments[i], classpath, baseLocation);
				addRuntimeLibraries(fragments[i], classpath, baseLocation);
				continue;
			}
			if ((afterPlugin && !isPatchFragment(fragments[i])) || all) {
				addRuntimeLibraries(fragments[i], classpath, baseLocation);
				addPluginLibrariesToFragmentLocations(plugin, fragments[i], classpath, baseLocation);
				continue;
			}
		}
	}

	private boolean isPatchFragment(BundleDescription fragment) throws CoreException {
		return generator.getSite(false).getRegistry().getPatchData().get(new Long(fragment.getBundleId())) != null;
	}

	/**
	 * There are cases where the plug-in only declares a library but the real JAR is under
	 * a fragment location. This method gets all the plugin libraries and place them in the
	 * possible fragment location.
	 * 
	 * @param plugin
	 * @param fragment
	 * @param classpath
	 * @param baseLocation
	 * @throws CoreException
	 */
	private void addPluginLibrariesToFragmentLocations(BundleDescription plugin, BundleDescription fragment, List<Object> classpath, String baseLocation) throws CoreException {
		//TODO This methods causes the addition of a lot of useless entries. See bug #35544
		//If we reintroduce the test below, we reintroduce the problem 35544	
		//	if (fragment.getRuntime() != null)
		//		return;
		String[] libraries = getClasspathEntries(plugin);

		String root = generator.getLocation(fragment);
		IPath base = Utils.makeRelative(new Path(root), new Path(baseLocation));
		Properties modelProps = getBuildPropertiesFor(fragment);
		for (int i = 0; i < libraries.length; i++) {
			addPathAndCheck(fragment, base, libraries[i], modelProps, classpath);
		}
	}

	private Properties getBuildPropertiesFor(BundleDescription bundle) {
		try {
			Properties bundleProperties = AbstractScriptGenerator.readProperties(generator.getLocation(bundle), PROPERTIES_FILE, IStatus.OK);
			if (Utils.isStringIn(generator.getClasspathEntries(bundle), ModelBuildScriptGenerator.DOT) != -1) {
				String sourceFolder = bundleProperties.getProperty(PROPERTY_SOURCE_PREFIX + ModelBuildScriptGenerator.DOT);
				if (sourceFolder != null) {
					bundleProperties.setProperty(PROPERTY_SOURCE_PREFIX + ModelBuildScriptGenerator.EXPANDED_DOT, sourceFolder);
					bundleProperties.remove(PROPERTY_SOURCE_PREFIX + ModelBuildScriptGenerator.DOT);
				}
				String outputValue = bundleProperties.getProperty(PROPERTY_OUTPUT_PREFIX + ModelBuildScriptGenerator.DOT);
				if (outputValue != null) {
					bundleProperties.setProperty(PROPERTY_OUTPUT_PREFIX + ModelBuildScriptGenerator.EXPANDED_DOT, outputValue);
					bundleProperties.remove(PROPERTY_OUTPUT_PREFIX + ModelBuildScriptGenerator.DOT);
				}
			}
			return bundleProperties;
		} catch (CoreException e) {
			//ignore
		}
		return null;
	}

	// Add a path into the classpath for a given model
	// pluginId the plugin we are adding to the classpath
	// basePath : the relative path between the plugin from which we are adding the classpath and the plugin that is requiring this entry 
	// classpath : The classpath in which we want to add this path 
	private void addPathAndCheck(BundleDescription model, IPath basePath, String libraryName, Properties modelProperties, List<Object> classpath) {
		String pluginKey = model != null ? model.getSymbolicName() + "_" + model.getVersion() : null; //$NON-NLS-1$
		String rules = ""; //$NON-NLS-1$
		//only add access rules to libraries that are not part of the current bundle
		//and are not this bundle's host if we are a fragment
		BundleDescription currentBundle = generator.getModel();
		if (model != null && model != currentBundle && (currentBundle.getHost() == null || currentBundle.getHost().getSupplier() != model)) {
			String packageKey = pluginKey;
			if (model.isResolved() && model.getHost() != null) {
				BundleDescription host = (BundleDescription) model.getHost().getSupplier();
				packageKey = host.getSymbolicName() + "_" + host.getVersion(); //$NON-NLS-1$
			}
			if (visiblePackages.containsKey(packageKey)) {
				rules = "[" + visiblePackages.get(packageKey) + File.pathSeparator + EXCLUDE_ALL_RULE + "]"; //$NON-NLS-1$ //$NON-NLS-2$
			} else {
				rules = "[" + EXCLUDE_ALL_RULE + "]"; //$NON-NLS-1$//$NON-NLS-2$
			}
		}

		String path = null;
		String subPath = null;
		Path libraryPath = new Path(libraryName);
		if (libraryPath.isAbsolute()) {
			path = libraryPath.toOSString();
		} else if ("jar".equalsIgnoreCase(basePath.getFileExtension())) { //$NON-NLS-1$
			if ("jar".equalsIgnoreCase(libraryPath.getFileExtension())) //$NON-NLS-1$
				subPath = libraryPath.toOSString();
			path = basePath.toOSString();
		} else {
			path = basePath.append(libraryPath).toOSString();
		}
		path = ModelBuildScriptGenerator.replaceVariables(path, pluginKey == null ? false : generator.getCompiledElements().contains(pluginKey));
		String secondaryPath = null;
		if (generator.getCompiledElements().contains(pluginKey)) {
			if (modelProperties == null || modelProperties.getProperty(IBuildPropertiesConstants.PROPERTY_SOURCE_PREFIX + libraryName) != null)
				path = Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER) + '/' + path;
			secondaryPath = Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER) + "/../" + model.getSymbolicName() + '_' + model.getVersion() + '/' + libraryName; //$NON-NLS-1$

		}

		addClasspathElementWithRule(classpath, path, subPath, rules);
		if (secondaryPath != null) {
			addClasspathElementWithRule(classpath, secondaryPath, null, rules);
		}
	}

	private void addClasspathElementWithRule(List<Object> classpath, String path, String subPath, String rules) {
		path = normalize(path);
		subPath = normalize(subPath);

		String elementsKey = subPath != null ? path + '/' + subPath : path;
		ClasspathElement existing = pathElements.get(elementsKey);
		if (existing != null) {
			existing.addRules(rules);
		} else {
			ClasspathElement element = new ClasspathElement(path, subPath, rules);
			classpath.add(element);
			pathElements.put(elementsKey, element);
		}
	}

	private void addSelf(BundleDescription model, ModelBuildScriptGenerator.CompiledEntry jar, List<Object> classpath, String location, List<BundleDescription> pluginChain, Set<BundleDescription> addedPlugins) throws CoreException {
		// If model is a fragment, we need to add in the classpath the plugin to which it is related
		HostSpecification host = model.getHost();
		if (host != null) {
			BundleDescription[] hosts = host.getHosts();
			for (int i = 0; i < hosts.length; i++)
				addPluginAndPrerequisites(hosts[i], classpath, location, pluginChain, addedPlugins);
		}

		// Add the libraries
		Properties modelProperties = generator.getBuildProperties();
		String jarOrder = (String) modelProperties.get(PROPERTY_JAR_ORDER);
		if (jarOrder == null) {
			// if no jar order was specified in build.properties, we add all the libraries but the current one
			// based on the order specified by the plugin.xml. Both library that we compile and .jar provided are processed
			String[] libraries = getClasspathEntries(model);
			if (libraries != null) {
				for (int i = 0; i < libraries.length; i++) {
					String libraryName = libraries[i];
					if (jar.getName(false).equals(libraryName))
						continue;

					boolean isSource = (modelProperties.getProperty(PROPERTY_SOURCE_PREFIX + libraryName) != null);
					if (isSource) {
						addDevEntries(model, location, classpath, Utils.getArrayFromString(modelProperties.getProperty(PROPERTY_OUTPUT_PREFIX + libraryName)), modelProperties);
					}
					//Potential pb: here there maybe a nasty case where the libraries variable may refer to something which is part of the base
					//but $xx$ will replace it by the $xx instead of $basexx. The solution is for the user to use the explicitly set the content
					// of its build.property file
					addPathAndCheck(model, Path.EMPTY, libraryName, modelProperties, classpath);
				}
			}
		} else {
			// otherwise we add all the predecessor jars
			String[] order = Utils.getArrayFromString(jarOrder);
			for (int i = 0; i < order.length; i++) {
				if (order[i].equals(jar.getName(false)))
					break;
				addDevEntries(model, location, classpath, Utils.getArrayFromString((String) modelProperties.get(PROPERTY_OUTPUT_PREFIX + order[i])), modelProperties);
				addPathAndCheck(model, Path.EMPTY, order[i], modelProperties, classpath);
			}
			// Then we add all the "pure libraries" (the one that does not contain source)
			String[] libraries = getClasspathEntries(model);
			for (int i = 0; i < libraries.length; i++) {
				String libraryName = libraries[i];
				if (modelProperties.get(PROPERTY_SOURCE_PREFIX + libraryName) == null) {
					//Potential pb: if the pure library is something that is being compiled (which is supposetly not the case, but who knows...)
					//the user will get $basexx instead of $ws 
					addPathAndCheck(model, Path.EMPTY, libraryName, modelProperties, classpath);
				}
			}
		}

		// add extra classpath if it exists. this code is kept for backward compatibility
		String extraClasspath = (String) modelProperties.get(PROPERTY_JAR_EXTRA_CLASSPATH);
		if (extraClasspath != null) {
			String[] extra = Utils.getArrayFromString(extraClasspath, ";,"); //$NON-NLS-1$

			for (int i = 0; i < extra.length; i++) {
				//Potential pb: if the path refers to something that is being compiled (which is supposetly not the case, but who knows...)
				//the user will get $basexx instead of $ws 
				String[] toAdd = computeExtraPath(extra[i], classpath, location);
				if (toAdd != null && toAdd.length == 2)
					addPathAndCheck(null, new Path(toAdd[0]), toAdd[1], modelProperties, classpath);
			}
		}

		//	add extra classpath if it is specified for the given jar
		String[] jarSpecificExtraClasspath = jar.getExtraClasspath();
		for (int i = 0; i < jarSpecificExtraClasspath.length; i++) {
			//Potential pb: if the path refers to something that is being compiled (which is supposetly not the case, but who knows...)
			//the user will get $basexx instead of $ws 
			String[] toAdd = computeExtraPath(jarSpecificExtraClasspath[i], classpath, location);
			if (toAdd != null && toAdd.length == 2)
				addPathAndCheck(null, new Path(toAdd[0]), toAdd[1], modelProperties, classpath);
		}
	}

	/** 
	 * Convenience method that compute the relative classpath of extra.classpath entries  
	 * @param url a url
	 * @param location location used as a base location to compute the relative path 
	 * @return String the relative path 
	 * @throws CoreException
	 */
	private String[] computeExtraPath(String url, List<Object> classpath, String location) throws CoreException {
		String relativePath = null;

		String[] urlfragments = Utils.getArrayFromString(url, "/"); //$NON-NLS-1$

		// A valid platform url for a plugin has a leat 3 segments.
		if (urlfragments.length > 2 && urlfragments[0].equals(PlatformURLHandler.PROTOCOL + PlatformURLHandler.PROTOCOL_SEPARATOR)) {
			String bundleLocation = null;
			BundleDescription bundle = null;
			if (urlfragments[1].equalsIgnoreCase(PLUGIN) || urlfragments[1].equalsIgnoreCase(FRAGMENT)) {
				bundle = generator.getSite(false).getRegistry().getResolvedBundle(urlfragments[2]);
				if (bundle == null) {
					String message = NLS.bind(Messages.exception_url, generator.getModel().getSymbolicName() + '/' + generator.getPropertiesFileName() + ": " + url); //$NON-NLS-1$
					MultiStatus status = new MultiStatus(PI_PDEBUILD, EXCEPTION_MALFORMED_URL, message, null);
					message = NLS.bind(Messages.exception_missingElement, urlfragments[2]);
					status.add(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PLUGIN_MISSING, message, null));
					throw new CoreException(status);
				}

				if (urlfragments.length == 3) {
					addPlugin(bundle, classpath, location);
					return null;
				}

				bundleLocation = generator.getLocation(bundle);
				if (bundleLocation != null) {
					String entry = urlfragments[3];
					for (int i = 4; i < urlfragments.length; i++) {
						entry += '/' + urlfragments[i];
					}
					return new String[] {Utils.makeRelative(new Path(bundleLocation), new Path(location)).toOSString(), entry};
				}
			} else if (urlfragments[1].equalsIgnoreCase("resource")) { //$NON-NLS-1$
				String message = NLS.bind(Messages.exception_url, generator.getModel().getSymbolicName() + '/' + generator.getPropertiesFileName() + ": " + url); //$NON-NLS-1$
				throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_MALFORMED_URL, message, null));
			}
		}

		// Then it's just a regular URL, or just something that will be added at the end of the classpath for backward compatibility.......
		try {
			URL extraURL = new URL(url);
			try {
				relativePath = Utils.makeRelative(new Path(FileLocator.resolve(extraURL).getFile()), new Path(location)).toOSString();
			} catch (IOException e) {
				String message = NLS.bind(Messages.exception_url, generator.getModel().getSymbolicName() + '/' + generator.getPropertiesFileName() + ": " + url); //$NON-NLS-1$
				throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_MALFORMED_URL, message, e));
			}
		} catch (MalformedURLException e) {
			relativePath = url;
			//TODO remove this backward compatibility support for as soon as we go to 2.2 and put back the exception
			//		String message = Policy.bind("exception.url", PROPERTIES_FILE + "::"+url); //$NON-NLS-1$  //$NON-NLS-2$
			//		throw new CoreException(new Status(IStatus.ERROR,PI_PDEBUILD, IPDEBuildConstants.EXCEPTION_MALFORMED_URL, message,e));
		}
		return new String[] {relativePath, ""}; //$NON-NLS-1$
	}

	//Add the prerequisite of a given plugin (target)
	private void addPrerequisites(BundleDescription target, List<Object> classpath, String baseLocation, List<BundleDescription> pluginChain, Set<BundleDescription> addedPlugins) throws CoreException {
		if (pluginChain.contains(target)) {
			if (allowBinaryCycles && isAllowableCycle(target, pluginChain)) {
				return;
			}
			// else exception
			String cycleString = ""; //$NON-NLS-1$
			for (Iterator<BundleDescription> iter = pluginChain.iterator(); iter.hasNext();)
				cycleString += iter.next().toString() + ", "; //$NON-NLS-1$
			cycleString += target.toString();
			String message = NLS.bind(Messages.error_pluginCycle, cycleString);
			throw new CoreException(new Status(IStatus.ERROR, IPDEBuildConstants.PI_PDEBUILD, EXCEPTION_CLASSPATH_CYCLE, message, null));
		}
		if (addedPlugins.contains(target)) //the plugin we are considering has already been added	
			return;

		// add libraries from pre-requisite plug-ins.  Don't worry about the export flag
		// as all required plugins may be required for compilation.
		BundleDescription[] requires = PDEState.getDependentBundles(target);
		pluginChain.add(target);
		for (int i = 0; i < requires.length; i++) {
			addPluginAndPrerequisites(requires[i], classpath, baseLocation, pluginChain, addedPlugins);
		}
		pluginChain.remove(target);
		addedPlugins.add(target);
	}

	/* We can allow a cycle if it only contains 1 bundle that needs to be built and the rest are  binary. */
	private boolean isAllowableCycle(BundleDescription target, List<BundleDescription> pluginChain) {
		boolean haveNonBinary = false;
		boolean inCycle = false;
		for (Iterator<BundleDescription> iterator = pluginChain.iterator(); iterator.hasNext();) {
			BundleDescription bundle = iterator.next();
			if (bundle == target) {
				inCycle = true;
				haveNonBinary = !Utils.isBinary(bundle);
				continue;
			}
			if (inCycle && !Utils.isBinary(bundle)) {
				if (haveNonBinary)
					return false;
				haveNonBinary = true;
			}
		}
		return true;
	}

	/**
	 * The pluginChain parameter is used to keep track of possible cycles. If prerequisite is already
	 * present in the chain it is not included in the classpath.
	 * 
	 * @param target : the plugin for which we are going to introduce
	 * @param classpath 
	 * @param baseLocation
	 * @param pluginChain
	 * @param addedPlugins
	 * @throws CoreException
	 */
	private void addPluginAndPrerequisites(BundleDescription target, List<Object> classpath, String baseLocation, List<BundleDescription> pluginChain, Set<BundleDescription> addedPlugins) throws CoreException {
		if (matchFilter(target) == false)
			return;

		addPlugin(target, classpath, baseLocation);
		addPrerequisites(target, classpath, baseLocation, pluginChain, addedPlugins);
	}

	private boolean matchFilter(BundleDescription target) {
		Filter filter = BundleHelper.getDefault().getFilter(target);
		if (filter == null) //Target is platform independent, add it 
			return true;

		FeatureEntry associatedEntry = generator.getAssociatedEntry();
		if (associatedEntry == null)
			return true;

		String os = associatedEntry.getOS();
		String ws = associatedEntry.getWS();
		String arch = associatedEntry.getArch();
		String nl = associatedEntry.getNL();
		if (os == null && ws == null && arch == null && nl == null) //I'm a platform independent plugin
			return true;

		//The plugin for which we are generating the classpath and target are not platform independent
		Dictionary<String, Object> properties = new Hashtable<>(3);
		if (os != null) {
			Object value = os.indexOf(',') > -1 ? (Object) Utils.getArrayFromString(os, ",") : os; //$NON-NLS-1$
			properties.put(OSGI_OS, value);
		} else {
			properties.put(OSGI_OS, CatchAllValue.singleton);
		}
		if (ws != null) {
			Object value = ws.indexOf(',') > -1 ? (Object) Utils.getArrayFromString(ws, ",") : ws; //$NON-NLS-1$
			properties.put(OSGI_WS, value);
		} else
			properties.put(OSGI_WS, CatchAllValue.singleton);

		if (arch != null) {
			Object value = arch.indexOf(',') > -1 ? (Object) Utils.getArrayFromString(arch, ",") : arch; //$NON-NLS-1$
			properties.put(OSGI_ARCH, value);
		} else
			properties.put(OSGI_ARCH, CatchAllValue.singleton);

		if (nl != null) {
			Object value = nl.indexOf(',') > -1 ? (Object) Utils.getArrayFromString(nl, ",") : nl; //$NON-NLS-1$
			properties.put(OSGI_NL, value);
		} else
			properties.put(OSGI_NL, CatchAllValue.singleton);

		return filter.match(properties);
	}

	/**
	 * 
	 * @param model
	 * @param baseLocation
	 * @param classpath
	 */
	private void addDevEntries(BundleDescription model, String baseLocation, List<Object> classpath, String[] jarSpecificEntries, Properties modelProperties) {
		if (generator.devEntries == null && (jarSpecificEntries == null || jarSpecificEntries.length == 0))
			return;

		String[] entries;
		// if jarSpecificEntries is given, then it overrides devEntries 
		if (jarSpecificEntries != null && jarSpecificEntries.length > 0)
			entries = jarSpecificEntries;
		else
			entries = generator.devEntries.getDevClassPath(model.getSymbolicName());

		IPath root = Utils.makeRelative(new Path(generator.getLocation(model)), new Path(baseLocation));
		for (int i = 0; i < entries.length; i++) {
			addPathAndCheck(model, root, entries[i], modelProperties, classpath);
		}
	}

	//Return the jar name from the classpath 
	private String[] getClasspathEntries(BundleDescription bundle) throws CoreException {
		return generator.getClasspathEntries(bundle);
	}
}
