/*******************************************************************************
 * 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(Long.valueOf(plugin.getBundleId()));
		if (patchInfo != null && plugin != generator.getModel()) {
			addFragmentsLibraries(plugin, classpath, location, false, false);
			allFragments = false;
		}

		requiredIds.add(Long.valueOf(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(Long.valueOf(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(Long.valueOf(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);
	}
}
