/*******************************************************************************
 * Copyright (c) 2000, 2018 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 Corporation - initial API and implementation
 *     Thierry Lach (thierry.lach@bbdodetroit.com) - bug 40502
 *     Ericsson AB, Hamdan Msheik - Bug 389564
 *     Ericsson AB, Julian Enoch - Bug 389564
 *******************************************************************************/
package org.eclipse.ant.core;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.ant.internal.core.AntClasspathEntry;
import org.eclipse.ant.internal.core.AntObject;
import org.eclipse.ant.internal.core.IAntCoreConstants;
import org.eclipse.ant.internal.core.InternalCoreAntMessages;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.core.variables.IDynamicVariable;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.util.tracker.ServiceTracker;

/**
 * Represents the Ant Core plug-in's preferences providing utilities for extracting, changing and updating the underlying preferences. Clients may not
 * instantiate or subclass this class.
 * 
 * @since 2.1
 * @noinstantiate This class is not intended to be instantiated by clients.
 * @noextend This class is not intended to be subclassed by clients.
 */
@SuppressWarnings("deprecation")
public class AntCorePreferences implements IPropertyChangeListener {

	class WrappedClassLoader extends ClassLoader {
		private Bundle bundle;

		public WrappedClassLoader(Bundle bundle) {
			super();
			this.bundle = bundle;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.ClassLoader#findClass(java.lang.String)
		 */
		@Override
		public Class<?> findClass(String name) throws ClassNotFoundException {
			return bundle.loadClass(name);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.ClassLoader#findResource(java.lang.String)
		 */
		@Override
		public URL findResource(String name) {
			return bundle.getResource(name);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.ClassLoader#findResources(java.lang.String)
		 */
		@Override
		protected Enumeration<URL> findResources(String name) throws IOException {
			return bundle.getResources(name);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object obj) {
			if (!(obj instanceof WrappedClassLoader)) {
				return false;
			}
			return bundle == ((WrappedClassLoader) obj).bundle;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Object#hashCode()
		 */
		@Override
		public int hashCode() {
			return bundle.hashCode();
		}

		@Override
		public String toString() {
			return "WrappedClassLoader(" + bundle.toString() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	static private class Relation {
		BundleRevision from;
		BundleRevision to;

		Relation(BundleRevision from, BundleRevision to) {
			this.from = from;
			this.to = to;
		}

		@Override
		public String toString() {
			return from.toString() + "->" + (to == null ? IAntCoreConstants.EMPTY_STRING : to.toString()); //$NON-NLS-1$
		}
	}

	private IPreferenceChangeListener prefListener = new IPreferenceChangeListener() {
		@Override
		public void preferenceChange(PreferenceChangeEvent event) {
			String property = event.getKey();
			if (property.equals(IAntCoreConstants.PREFERENCE_TASKS) || property.startsWith(IAntCoreConstants.PREFIX_TASK)) {
				restoreTasks();
			} else if (property.equals(IAntCoreConstants.PREFERENCE_TYPES) || property.startsWith(IAntCoreConstants.PREFIX_TYPE)) {
				restoreTypes();
			} else if (property.equals(IAntCoreConstants.PREFERENCE_ANT_HOME_ENTRIES)) {
				restoreAntHomeEntries();
			} else if (property.equals(IAntCoreConstants.PREFERENCE_ADDITIONAL_ENTRIES)) {
				restoreAdditionalEntries();
			} else if (property.equals(IAntCoreConstants.PREFERENCE_ANT_HOME)) {
				restoreAntHome();
			} else if (property.equals(IAntCoreConstants.PREFERENCE_PROPERTIES) || property.startsWith(IAntCoreConstants.PREFIX_PROPERTY)) {
				restoreCustomProperties();
			} else if (property.equals(IAntCoreConstants.PREFERENCE_PROPERTY_FILES)) {
				restoreCustomPropertyFiles();
			}
		}
	};

	private List<Task> defaultTasks;
	private List<Type> defaultTypes;
	private List<AntClasspathEntry> extraClasspathURLs;
	private List<Property> defaultProperties;
	private IAntClasspathEntry[] defaultAntHomeEntries;

	private Task[] customTasks;
	private Task[] oldCustomTasks;
	private Type[] customTypes;
	private Type[] oldCustomTypes;
	private IAntClasspathEntry[] antHomeEntries;
	private IAntClasspathEntry[] additionalEntries;
	private Property[] customProperties;
	private Property[] oldCustomProperties;
	private String[] customPropertyFiles;

	private List<WrappedClassLoader> pluginClassLoaders;

	private ClassLoader[] orderedPluginClassLoaders;

	private String antHome;

	private boolean runningHeadless = false;

	protected AntCorePreferences(List<IConfigurationElement> defaultTasks, List<IConfigurationElement> defaultExtraClasspath, List<IConfigurationElement> defaultTypes, boolean headless) {
		this(defaultTasks, defaultExtraClasspath, defaultTypes, Collections.<IConfigurationElement> emptyList(), headless);
	}

	protected AntCorePreferences(List<IConfigurationElement> defaultTasks, List<IConfigurationElement> defaultExtraClasspath, List<IConfigurationElement> defaultTypes, List<IConfigurationElement> defaultProperties, boolean headless) {
		runningHeadless = headless;
		initializePluginClassLoaders();
		extraClasspathURLs = new ArrayList<>(20);
		this.defaultTasks = computeDefaultTasks(defaultTasks);
		this.defaultTypes = computeDefaultTypes(defaultTypes);
		computeDefaultExtraClasspathEntries(defaultExtraClasspath);
		computeDefaultProperties(defaultProperties);
		restoreCustomObjects();

	}

	/**
	 * When a preference changes, update the in-memory cache of the preference.
	 * 
	 * @param event
	 *            The property change event that has occurred.
	 * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)
	 */
	@Override
	public void propertyChange(Preferences.PropertyChangeEvent event) {
		// does nothing any longer, see the IPreferenceChangedListener field
	}

	/**
	 * Restores the in-memory model of the preferences from the preference store
	 */
	private void restoreCustomObjects() {
		restoreAntHome();
		restoreTasks();
		restoreTypes();
		restoreAntHomeEntries();
		restoreAdditionalEntries();
		restoreCustomProperties();
		restoreCustomPropertyFiles();
		IEclipsePreferences node = InstanceScope.INSTANCE.getNode(AntCorePlugin.PI_ANTCORE);
		if (node != null) {
			node.addPreferenceChangeListener(prefListener);
		}
	}

	private void restoreTasks() {
		String tasks = Platform.getPreferencesService().getString(AntCorePlugin.PI_ANTCORE, IAntCoreConstants.PREFERENCE_TASKS, null, null);
		if (tasks == null || IAntCoreConstants.EMPTY_STRING.equals(tasks)) {
			customTasks = new Task[0];
		} else {
			customTasks = extractTasks(AntCorePlugin.getPlugin().getPluginPreferences(), getArrayFromString(tasks));
		}
	}

	private void restoreTypes() {
		String types = Platform.getPreferencesService().getString(AntCorePlugin.PI_ANTCORE, IAntCoreConstants.PREFERENCE_TYPES, null, null);
		if (types == null || IAntCoreConstants.EMPTY_STRING.equals(types)) {
			customTypes = new Type[0];
		} else {
			customTypes = extractTypes(AntCorePlugin.getPlugin().getPluginPreferences(), getArrayFromString(types));
		}
	}

	private void restoreAntHomeEntries() {
		String entries = Platform.getPreferencesService().getString(AntCorePlugin.PI_ANTCORE, "ant_urls", //$NON-NLS-1$
				null, null); // old constant
		if (entries == null || IAntCoreConstants.EMPTY_STRING.equals(entries)) {
			entries = Platform.getPreferencesService().getString(AntCorePlugin.PI_ANTCORE, IAntCoreConstants.PREFERENCE_ANT_HOME_ENTRIES, null, null);
		} else {
			// torch the old pref
			IEclipsePreferences node = InstanceScope.INSTANCE.getNode(AntCorePlugin.PI_ANTCORE);
			if (node != null) {
				node.remove("ant_urls"); //$NON-NLS-1$
				try {
					node.flush();
				}
				catch (BackingStoreException e) {
					// do nothing
				}
			}
			antHomeEntries = migrateURLEntries(getArrayFromString(entries));
			return;
		}
		if (entries == null || IAntCoreConstants.EMPTY_STRING.equals(entries)) {
			antHomeEntries = getDefaultAntHomeEntries();
		} else {
			antHomeEntries = extractEntries(getArrayFromString(entries));
		}
	}

	private void restoreAdditionalEntries() {
		String entries = Platform.getPreferencesService().getString(AntCorePlugin.PI_ANTCORE, "urls", //$NON-NLS-1$
				null, null); // old constant
		if (entries == null || IAntCoreConstants.EMPTY_STRING.equals(entries)) {
			entries = Platform.getPreferencesService().getString(AntCorePlugin.PI_ANTCORE, IAntCoreConstants.PREFERENCE_ADDITIONAL_ENTRIES, null, null);
		} else {
			IEclipsePreferences node = InstanceScope.INSTANCE.getNode(AntCorePlugin.PI_ANTCORE);
			if (node != null) {
				node.remove("urls"); //$NON-NLS-1$
				try {
					node.flush();
				}
				catch (BackingStoreException e) {
					// do nothing
				}
			}
			additionalEntries = migrateURLEntries(getArrayFromString(entries));
			return;
		}
		if (entries == null || IAntCoreConstants.EMPTY_STRING.equals(entries)) {
			IAntClasspathEntry toolsJarEntry = getToolsJarEntry();
			List<IAntClasspathEntry> userLibs = getUserLibraries();
			if (toolsJarEntry == null) {
				if (userLibs == null) {
					additionalEntries = new IAntClasspathEntry[0];
				} else {
					additionalEntries = userLibs.toArray(new IAntClasspathEntry[userLibs.size()]);
				}
			} else {
				if (userLibs == null) {
					additionalEntries = new IAntClasspathEntry[] { toolsJarEntry };
				} else {
					userLibs.add(toolsJarEntry);
					additionalEntries = userLibs.toArray(new IAntClasspathEntry[userLibs.size()]);
				}
			}
		} else {
			additionalEntries = extractEntries(getArrayFromString(entries));
		}
	}

	/*
	 * Migrates the persisted URL entries restored from a workspace older than 3.0
	 */
	private IAntClasspathEntry[] migrateURLEntries(String[] urlEntries) {
		List<AntClasspathEntry> result = new ArrayList<>(urlEntries.length);
		for (int i = 0; i < urlEntries.length; i++) {
			URL url;
			try {
				url = new URL(urlEntries[i]);
			}
			catch (MalformedURLException e) {
				continue;
			}
			result.add(new AntClasspathEntry(url));
		}
		return result.toArray(new IAntClasspathEntry[result.size()]);
	}

	private void restoreAntHome() {
		antHome = Platform.getPreferencesService().getString(AntCorePlugin.PI_ANTCORE, IAntCoreConstants.PREFERENCE_ANT_HOME, null, null);
		if (antHome == null || IAntCoreConstants.EMPTY_STRING.equals(antHome)) {
			antHome = getDefaultAntHome();
		}
	}

	/**
	 * Returns the absolute path of the default ant.home to use for the build. The default is the org.apache.ant plug-in folder provided with Eclipse.
	 * 
	 * @return String absolute path of the default ant.home
	 * @since 3.0
	 */
	public String getDefaultAntHome() {
		IAntClasspathEntry[] entries = getDefaultAntHomeEntries();
		if (entries.length > 0) {
			URL antjar = entries[entries.length - 1].getEntryURL();
			IPath antHomePath = new Path(antjar.getFile());
			// parent directory of the lib directory
			antHomePath = antHomePath.removeLastSegments(2);
			return antHomePath.toFile().getAbsolutePath();
		}
		return null;
	}

	private void restoreCustomProperties() {
		String properties = Platform.getPreferencesService().getString(AntCorePlugin.PI_ANTCORE, IAntCoreConstants.PREFERENCE_PROPERTIES, null, null);
		if (properties == null || IAntCoreConstants.EMPTY_STRING.equals(properties)) {
			customProperties = new Property[0];
		} else {
			customProperties = extractProperties(AntCorePlugin.getPlugin().getPluginPreferences(), getArrayFromString(properties));
		}
	}

	private void restoreCustomPropertyFiles() {
		String propertyFiles = Platform.getPreferencesService().getString(AntCorePlugin.PI_ANTCORE, IAntCoreConstants.PREFERENCE_PROPERTY_FILES, null, null);
		if (propertyFiles == null || IAntCoreConstants.EMPTY_STRING.equals(propertyFiles)) {
			customPropertyFiles = new String[0];
		} else {
			customPropertyFiles = getArrayFromString(propertyFiles);
		}
	}

	protected Task[] extractTasks(Preferences prefs, String[] tasks) {
		List<Task> result = new ArrayList<>(tasks.length);
		for (int i = 0; i < tasks.length; i++) {
			String taskName = tasks[i];
			String[] values = getArrayFromString(prefs.getString(IAntCoreConstants.PREFIX_TASK + taskName));
			if (values.length < 2) {
				continue;
			}
			Task task = new Task();
			task.setTaskName(taskName);
			task.setClassName(values[0]);
			String library = values[1];
			if (library.startsWith(IAntCoreConstants.FILE_PROTOCOL)) {
				// old format where URLs were persisted
				library = library.substring(5);
			}
			task.setLibraryEntry(new AntClasspathEntry(library));
			result.add(task);
		}
		return result.toArray(new Task[result.size()]);
	}

	protected Type[] extractTypes(Preferences prefs, String[] types) {
		List<Type> result = new ArrayList<>(types.length);
		for (int i = 0; i < types.length; i++) {
			String typeName = types[i];
			String[] values = getArrayFromString(prefs.getString(IAntCoreConstants.PREFIX_TYPE + typeName));
			if (values.length < 2) {
				continue;
			}
			Type type = new Type();
			type.setTypeName(typeName);
			type.setClassName(values[0]);
			String library = values[1];
			if (library.startsWith(IAntCoreConstants.FILE_PROTOCOL)) {
				// old format where URLs were persisted
				library = library.substring(5);
			}
			type.setLibraryEntry(new AntClasspathEntry(library));
			result.add(type);
		}
		return result.toArray(new Type[result.size()]);
	}

	protected Property[] extractProperties(Preferences prefs, String[] properties) {
		Property[] result = new Property[properties.length];
		for (int i = 0; i < properties.length; i++) {
			String propertyName = properties[i];
			String value = prefs.getString(IAntCoreConstants.PREFIX_PROPERTY + propertyName);
			Property property = new Property();
			property.setName(propertyName);
			property.setValue(value);
			result[i] = property;
		}
		return result;
	}

	private IAntClasspathEntry[] extractEntries(String[] entries) {
		IAntClasspathEntry[] result = new IAntClasspathEntry[entries.length];
		for (int i = 0; i < entries.length; i++) {
			result[i] = new AntClasspathEntry(entries[i]);
		}
		return result;
	}

	/**
	 * Returns the array of URLs that is the default set of URLs defining the Ant classpath.
	 * 
	 * Ant running through the command line tries to find tools.jar to help the user. Try emulating the same behavior here.
	 * 
	 * @return the default set of URLs defining the Ant classpath
	 * @deprecated use {@link #getDefaultAntHomeEntries()} instead
	 */
	@Deprecated
	public URL[] getDefaultAntURLs() {
		IAntClasspathEntry[] entries = getDefaultAntHomeEntries();
		List<URL> result = new ArrayList<>(3);
		for (int i = 0; i < entries.length; i++) {
			IAntClasspathEntry entry = entries[i];
			result.add(entry.getEntryURL());
		}
		URL toolsURL = getToolsJarURL();
		if (toolsURL != null) {
			result.add(toolsURL);
		}
		return result.toArray(new URL[result.size()]);
	}

	/**
	 * Returns the array of classpath entries that is the default set of entries defining the Ant classpath.
	 * 
	 * @return the default set of classpath entries defining the Ant classpath
	 */
	public synchronized IAntClasspathEntry[] getDefaultAntHomeEntries() {
		if (defaultAntHomeEntries == null) {
			ServiceTracker<?, ?> tracker = new ServiceTracker<>(AntCorePlugin.getPlugin().getBundle().getBundleContext(), PackageAdmin.class.getName(), null);
			tracker.open();
			try {
				List<AntClasspathEntry> result = new ArrayList<>(29);
				PackageAdmin packageAdmin = (PackageAdmin) tracker.getService();
				if (packageAdmin != null) {
					ExportedPackage[] packages = packageAdmin.getExportedPackages("org.apache.tools.ant"); //$NON-NLS-1$
					Bundle bundle = findHighestAntVersion(packages);
					if (bundle == null) {
						for (int i = 0; i < packages.length; i++) {
							bundle = packages[i].getExportingBundle();
							if (bundle == null) {
								continue;
							}
							try {
								addLibraries(bundle, result);
								if (result.size() > 0) {
									break;
								}
							}
							catch (IOException ioe) {
								AntCorePlugin.log(ioe); // maintain logging
								result.clear();
								/* continue to try other providers if an exception occurs */
							}
						}
					} else {
						try {
							addLibraries(bundle, result);
						}
						catch (IOException ioe) {
							AntCorePlugin.log(ioe); // maintain logging
						}
					}
				}
				defaultAntHomeEntries = result.toArray(new IAntClasspathEntry[result.size()]);
			}
			finally {
				tracker.close();
			}
		}
		return defaultAntHomeEntries;
	}

	/**
	 * Simple algorithm to find the highest version of <code>org.apache.ant</code> available. If there are other providers that are not
	 * <code>org.apache.ant</code> they are ignored and all versions of <code>org.apache.ant</code> are considered. <br>
	 * <br>
	 * See the following bugs for related history:
	 * <ul>
	 * <li><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=282851">https://bugs.eclipse.org/bugs/show_bug.cgi?id=282851</a></li>
	 * <li><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=325125">https://bugs.eclipse.org/bugs/show_bug.cgi?id=325125</a></li>
	 * </ul>
	 * 
	 * @param packages
	 *            the live list of {@link ExportedPackage}s to inspect
	 * @return the bundle that represents the highest version of <code>org.apache.ant</code> or <code>null</code> if there are no
	 *         <code>org.apache.ant</code> providers of the <code>org.apache.ant.tools</code> package.
	 */
	Bundle findHighestAntVersion(ExportedPackage[] packages) {
		Bundle bundle = null;
		HashSet<Bundle> bundles = new HashSet<>();
		for (int i = 0; i < packages.length; i++) {
			bundle = packages[i].getExportingBundle();
			if (bundle == null) {
				continue;
			}
			if ("org.apache.ant".equals(bundle.getSymbolicName())) { //$NON-NLS-1$
				bundles.add(bundle);
			}
		}
		Bundle highest = null;
		Bundle temp = null;
		for (Iterator<Bundle> iter = bundles.iterator(); iter.hasNext();) {
			temp = iter.next();
			if (highest == null) {
				highest = temp;
			} else {
				if (highest.getVersion().compareTo(temp.getVersion()) < 0) {
					highest = temp;
				}
			}
		}
		return highest;
	}

	/**
	 * Returns the array of URLs that is the set of URLs defining the Ant classpath.
	 * 
	 * @return the set of URLs defining the Ant classpath
	 * @deprecated use getAntHomeClasspathEntries and getToolsJarEntry
	 */
	@Deprecated
	public URL[] getAntURLs() {
		int extra = 0;
		IAntClasspathEntry entry = getToolsJarEntry();
		if (entry != null) {
			extra++;
		}
		URL[] urls = new URL[antHomeEntries.length + extra];
		int i;
		for (i = 0; i < antHomeEntries.length; i++) {
			URL url = antHomeEntries[i].getEntryURL();
			if (url != null) {
				urls[i] = url;
			}
		}
		if (entry != null) {
			urls[i] = entry.getEntryURL();
		}
		return urls;

	}

	/**
	 * Returns the complete list of pre-configured {@link Task}s
	 * 
	 * @param tasks
	 *            the {@link IConfigurationElement} handles for contributed {@link Task}s
	 * @return the list of {@link Task}s
	 */
	protected List<Task> computeDefaultTasks(List<IConfigurationElement> tasks) {
		List<Task> result = new ArrayList<>(tasks.size());
		for (Iterator<IConfigurationElement> iterator = tasks.iterator(); iterator.hasNext();) {
			IConfigurationElement element = iterator.next();
			if (!relevantRunningHeadless(element)) {
				continue;
			}
			Task task = new Task();
			task.setTaskName(element.getAttribute(IAntCoreConstants.NAME));
			task.setClassName(element.getAttribute(AntCorePlugin.CLASS));

			if (configureAntObject(element, task, task.getTaskName(), InternalCoreAntMessages.AntCorePreferences_No_library_for_task)) {
				result.add(task);
			}
		}
		return result;
	}

	private void addURLToExtraClasspathEntries(URL url, IConfigurationElement element) {
		String eclipseRuntime = element.getAttribute(AntCorePlugin.ECLIPSE_RUNTIME);
		boolean eclipseRuntimeRequired = true;
		if (eclipseRuntime != null) {
			eclipseRuntimeRequired = Boolean.valueOf(eclipseRuntime).booleanValue();
		}
		Iterator<AntClasspathEntry> itr = extraClasspathURLs.iterator();
		while (itr.hasNext()) {
			IAntClasspathEntry entry = itr.next();
			if (entry.getEntryURL().equals(url)) {
				return;
			}
		}

		AntClasspathEntry entry = new AntClasspathEntry(url);
		entry.setEclipseRuntimeRequired(eclipseRuntimeRequired);
		extraClasspathURLs.add(entry);
	}

	/**
	 * Returns the complete listing of pre-configured {@link Type}s
	 * 
	 * @param types
	 *            the list of {@link IConfigurationElement} handles to contributed {@link Type}s
	 * @return the list of {@link Type}s
	 */
	protected List<Type> computeDefaultTypes(List<IConfigurationElement> types) {
		List<Type> result = new ArrayList<>(types.size());
		for (Iterator<IConfigurationElement> iterator = types.iterator(); iterator.hasNext();) {
			IConfigurationElement element = iterator.next();
			if (!relevantRunningHeadless(element)) {
				continue;
			}
			Type type = new Type();
			type.setTypeName(element.getAttribute(IAntCoreConstants.NAME));
			type.setClassName(element.getAttribute(AntCorePlugin.CLASS));

			if (configureAntObject(element, type, type.getTypeName(), InternalCoreAntMessages.AntCorePreferences_No_library_for_type)) {
				result.add(type);
			}
		}
		return result;
	}

	/*
	 * Create a "file:" URL for the specified File making sure the URL ends with a slash if the File denotes a directory.
	 */
	private URL getClasspathEntryURL(Bundle bundle, String library) throws IOException {
		File urlFile = null;
		if (library.equals("/")) { //$NON-NLS-1$
			urlFile = FileLocator.getBundleFile(bundle);
		} else {
			try {
				URL fileURL = FileLocator.toFileURL(bundle.getEntry(library));
				if (fileURL != null) {
					urlFile = URIUtil.toFile(URIUtil.toURI(fileURL));
				}
			}
			catch (URISyntaxException e) {
				AntCorePlugin.log(e);
			}
		}

		if (urlFile == null || !urlFile.exists())
			return null;

		String path = urlFile.getAbsolutePath();
		return new URL(IAntCoreConstants.FILE_PROTOCOL + (urlFile.isDirectory() ? path + "/" : path)); //$NON-NLS-1$
	}

	/**
	 * Configures the given {@link AntObject} and returns if it should be retained
	 * 
	 * @param element
	 * @param antObject
	 * @param objectName
	 * @param errorMessage
	 * @return <code>true</code> if the object configured and should be retained, <code>false</code> otherwise
	 */
	private boolean configureAntObject(IConfigurationElement element, AntObject antObject, String objectName, String errorMessage) {
		String runtime = element.getAttribute(AntCorePlugin.ECLIPSE_RUNTIME);
		if (runtime != null) {
			antObject.setEclipseRuntimeRequired(Boolean.valueOf(runtime).booleanValue());
		}

		String uri = element.getAttribute(AntCorePlugin.URI);
		if (uri != null) {
			antObject.setURI(uri);
		}

		String library = element.getAttribute(AntCorePlugin.LIBRARY);
		if (library == null) {
			IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_LIBRARY_NOT_SPECIFIED, NLS.bind(InternalCoreAntMessages.AntCorePreferences_Library_not_specified_for___0__4, new String[] {
					objectName }), null);
			AntCorePlugin.getPlugin().getLog().log(status);
			return false;
		}

		try {
			IContributor contributor = element.getContributor();
			antObject.setPluginLabel(contributor.getName());
			Bundle bundle = Platform.getBundle(contributor.getName());
			URL url = getClasspathEntryURL(bundle, library);
			if (url != null) {
				addURLToExtraClasspathEntries(url, element);
				addPluginClassLoader(bundle);
				antObject.setLibraryEntry(new AntClasspathEntry(url));
				return true;
			}

			// type specifies a library that does not exist
			IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_LIBRARY_NOT_SPECIFIED, NLS.bind(errorMessage, new String[] {
					library, element.getContributor().getName() }), null);
			AntCorePlugin.getPlugin().getLog().log(status);
			return false;
		}
		catch (MalformedURLException e) {
			// if the URL does not have a valid format, just log and ignore the exception
			IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_MALFORMED_URL, InternalCoreAntMessages.AntCorePreferences_Malformed_URL__1, e);
			AntCorePlugin.getPlugin().getLog().log(status);
		}
		catch (Exception e) {
			// likely extra classpath entry library that does not exist
			IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_LIBRARY_NOT_SPECIFIED, NLS.bind(InternalCoreAntMessages.AntCorePreferences_8, new String[] {
					library, element.getContributor().getName() }), null);
			AntCorePlugin.getPlugin().getLog().log(status);
		}
		return false;
	}

	/*
	 * Computes the extra classpath entries defined plug-ins and fragments.
	 */
	protected void computeDefaultExtraClasspathEntries(List<IConfigurationElement> entries) {
		for (Iterator<IConfigurationElement> iterator = entries.iterator(); iterator.hasNext();) {
			IConfigurationElement element = iterator.next();
			if (!relevantRunningHeadless(element)) {
				continue;
			}
			String library = element.getAttribute(AntCorePlugin.LIBRARY);
			Bundle bundle = Platform.getBundle(element.getContributor().getName());
			try {
				URL url = getClasspathEntryURL(bundle, library);
				if (url != null) {
					addURLToExtraClasspathEntries(url, element);
					addPluginClassLoader(bundle);
				} else {
					// extra classpath entry that does not exist
					IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_LIBRARY_NOT_SPECIFIED, NLS.bind(InternalCoreAntMessages.AntCorePreferences_6, new String[] {
							library, element.getContributor().getName() }), null);
					AntCorePlugin.getPlugin().getLog().log(status);
					continue;
				}
			}
			catch (MalformedURLException e) {
				// if the URL does not have a valid format, just log and ignore the exception
				IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_MALFORMED_URL, InternalCoreAntMessages.AntCorePreferences_Malformed_URL__1, e);
				AntCorePlugin.getPlugin().getLog().log(status);
				continue;
			}
			catch (Exception e) {
				// likely extra classpath entry that does not exist
				IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_LIBRARY_NOT_SPECIFIED, NLS.bind(InternalCoreAntMessages.AntCorePreferences_6, new String[] {
						library, element.getContributor().getName() }), null);
				AntCorePlugin.getPlugin().getLog().log(status);
				continue;
			}
		}
	}

	private boolean relevantRunningHeadless(IConfigurationElement element) {
		if (runningHeadless) {
			String headless = element.getAttribute(AntCorePlugin.HEADLESS);
			if (headless != null) {
				boolean headlessProperty = Boolean.valueOf(headless).booleanValue();
				if (!headlessProperty) {
					return false;
				}
			}
		}
		return true;
	}

	/*
	 * Scan the Ant property extensions for properties to set.
	 * 
	 * @since 3.0
	 */
	private void computeDefaultProperties(List<IConfigurationElement> properties) {
		defaultProperties = new ArrayList<>(properties.size());
		for (Iterator<IConfigurationElement> iterator = properties.iterator(); iterator.hasNext();) {
			IConfigurationElement element = iterator.next();
			if (!relevantRunningHeadless(element)) {
				continue;
			}
			String name = element.getAttribute(IAntCoreConstants.NAME);
			if (name == null) {
				continue;
			}
			String value = element.getAttribute(IAntCoreConstants.VALUE);
			Property property = null;
			if (value != null) {
				property = new Property(name, value);
				property.setPluginLabel(element.getContributor().getName());
			} else {
				Bundle bundle = Platform.getBundle(element.getContributor().getName());
				if (bundle == null) {
					continue;
				}
				property = new Property();
				property.setName(name);
				property.setPluginLabel(element.getContributor().getName());
				String className = element.getAttribute(AntCorePlugin.CLASS);
				property.setValueProvider(className, getClassLoader(bundle));
			}
			defaultProperties.add(property);
			String runtime = element.getAttribute(AntCorePlugin.ECLIPSE_RUNTIME);
			if (runtime != null) {
				property.setEclipseRuntimeRequired(Boolean.valueOf(runtime).booleanValue());
			}
		}
	}

	private WrappedClassLoader getClassLoader(Bundle b) {
		return new WrappedClassLoader(b);
	}

	/**
	 * Returns the IAntClasspathEntry for the tools.jar associated with the path supplied. May return <code>null</code> if no tools.jar is found (e.g.
	 * the path points to a JRE install).
	 * 
	 * @param javaHomePath
	 *            path for Java home
	 * @return IAntClasspathEntry tools.jar IAntClasspathEntry or <code>null</code>
	 * @since 3.0
	 */
	public IAntClasspathEntry getToolsJarEntry(IPath javaHomePath) {
		IPath newjh = javaHomePath;
		if ("jre".equalsIgnoreCase(newjh.lastSegment())) { //$NON-NLS-1$
			newjh = newjh.removeLastSegments(1);
		}
		newjh = newjh.append("lib").append("tools.jar"); //$NON-NLS-1$ //$NON-NLS-2$
		File tools = newjh.toFile();
		if (!tools.exists()) {
			// attempt to find in the older 1.1.*
			newjh = newjh.removeLastSegments(1);
			newjh = newjh.append("classes.zip"); //$NON-NLS-1$
			tools = newjh.toFile();
			if (!tools.exists()) {
				return null;
			}
		}

		return new AntClasspathEntry(tools.getAbsolutePath());
	}

	/**
	 * Returns the URL for the tools.jar associated with the System property "java.home" location. If "java.home" has no associated tools.jar (such as
	 * a JRE install), the environment variable "JAVA_HOME" is resolved to check for a tools.jar. May return <code>null</code> if no tools.jar is
	 * found.
	 * 
	 * @return URL tools.jar URL or <code>null</code>
	 * @deprecated use getToolsJarEntry()
	 */
	@Deprecated
	public URL getToolsJarURL() {
		IPath path = new Path(System.getProperty("java.home")); //$NON-NLS-1$
		IAntClasspathEntry entry = getToolsJarEntry(path);
		if (entry == null) {
			IDynamicVariable variable = VariablesPlugin.getDefault().getStringVariableManager().getDynamicVariable("env_var"); //$NON-NLS-1$
			String javaHome = null;
			try {
				if (variable != null) {
					javaHome = variable.getValue("JAVA_HOME"); //$NON-NLS-1$
				}
				if (javaHome != null) {
					path = new Path(javaHome);
					entry = getToolsJarEntry(path);
				}
			}
			catch (CoreException e) {
				AntCorePlugin.log(e);
			}
		}
		if (entry != null) {
			return entry.getEntryURL();
		}
		return null;
	}

	/**
	 * Returns the <code>IAntClasspathEntry</code> for the tools.jar associated with the System property "java.home" location. If "java.home" has no
	 * associated tools.jar (such as a JRE install), the environment variable "JAVA_HOME" is resolved to check for a tools.jar. May return
	 * <code>null</code> if no tools.jar is found.
	 * 
	 * @return IAntClasspathEntry tools.jar IAntClasspathEntry or <code>null</code>
	 */
	public IAntClasspathEntry getToolsJarEntry() {
		IPath path = new Path(System.getProperty("java.home")); //$NON-NLS-1$
		IAntClasspathEntry entry = getToolsJarEntry(path);
		if (entry == null) {
			IDynamicVariable variable = VariablesPlugin.getDefault().getStringVariableManager().getDynamicVariable("env_var"); //$NON-NLS-1$
			String javaHome = null;
			try {
				if (variable != null) {
					javaHome = variable.getValue("JAVA_HOME"); //$NON-NLS-1$
				}
				if (javaHome != null) {
					path = new Path(javaHome);
					entry = getToolsJarEntry(path);
				}
			}
			catch (CoreException e) {
				AntCorePlugin.log(e);
			}
		}
		return entry;
	}

	/**
	 * Returns the <code>IAntClasspathEntry</code>s for the jars from ${user.home}/.ant/lib May return <code>null</code> if jars are found.
	 * 
	 * TODO Should be promoted to API post 3.1
	 * 
	 * @return the collection of <code>IAntClasspathEntry</code> found at ${user.home}/.ant/lib or <code>null</code> if none found of location does
	 *         not exist
	 */
	private List<IAntClasspathEntry> getUserLibraries() {
		File libDir = new File(System.getProperty("user.home"), ".ant" + File.separatorChar + "lib"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		URL[] urls = null;
		try {
			urls = getLocationURLs(libDir);
		}
		catch (MalformedURLException e) {
			AntCorePlugin.log(e);
		}
		if (urls == null) {
			return null;
		}

		List<IAntClasspathEntry> entries = new ArrayList<>(urls.length);
		for (int i = 0; i < urls.length; i++) {
			AntClasspathEntry entry = new AntClasspathEntry(urls[i]);
			entries.add(entry);
		}
		return entries;
	}

	private URL[] getLocationURLs(File location) throws MalformedURLException {
		URL[] urls = null;
		if (!location.exists()) {
			return urls;
		}
		final String extension = ".jar"; //$NON-NLS-1$
		if (!location.isDirectory()) {
			urls = new URL[1];
			String path = location.getPath();
			if (path.toLowerCase().endsWith(extension)) {
				// make sure the URL is properly escaped
				urls[0] = location.toURI().toURL();
			}
			return urls;
		}

		File[] matches = location.listFiles(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
				return name.toLowerCase().endsWith(extension);
			}
		});

		urls = new URL[matches.length];
		for (int i = 0; i < matches.length; ++i) {
			// make sure the URL is properly escaped
			urls[i] = matches[i].toURI().toURL();
		}
		return urls;
	}

	/**
	 * Add the libraries contributed by the Ant plug-in, to the classpath.
	 * 
	 * @param source
	 * @param destination
	 * @throws IOException
	 * @throws MalformedURLException
	 */
	private void addLibraries(Bundle source, List<AntClasspathEntry> destination) throws IOException, MalformedURLException {
		ManifestElement[] libraries = null;
		try {
			libraries = ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, source.getHeaders(IAntCoreConstants.EMPTY_STRING).get(Constants.BUNDLE_CLASSPATH));
		}
		catch (BundleException e) {
			IStatus status = new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_MALFORMED_URL, InternalCoreAntMessages.AntCorePreferences_0, e);
			AntCorePlugin.getPlugin().getLog().log(status);
			return;
		}
		if (libraries == null) {
			return;
		}
		URL url = null;
		for (int i = 0; i < libraries.length; i++) {
			url = source.getEntry(libraries[i].getValue());
			if (url != null) {
				destination.add(new AntClasspathEntry(FileLocator.toFileURL(url)));
			}
		}
	}

	protected void addPluginClassLoader(Bundle bundle) {
		WrappedClassLoader loader = getClassLoader(bundle);
		if (!pluginClassLoaders.contains(loader)) {
			pluginClassLoaders.add(loader);
		}
	}

	/**
	 * Returns the list of URLs added to the classpath by the extra classpath entries extension point.
	 * 
	 * @return the list of extra classpath URLs
	 */
	public URL[] getExtraClasspathURLs() {
		URL[] urls = new URL[extraClasspathURLs.size()];

		for (int i = 0; i < extraClasspathURLs.size(); i++) {
			IAntClasspathEntry entry = extraClasspathURLs.get(i);
			urls[i] = entry.getEntryURL();
		}
		return urls;
	}

	/**
	 * Returns the list of URLs added to the classpath by the extra classpath entries extension point for an Ant build that is occurring without the
	 * Eclipse runtime.
	 * 
	 * @return the list of extra classpath URLs
	 * @since 3.0
	 */
	public URL[] getRemoteExtraClasspathURLs() {
		List<URL> urls = new ArrayList<>(extraClasspathURLs.size());

		for (int i = 0; i < extraClasspathURLs.size(); i++) {
			IAntClasspathEntry entry = extraClasspathURLs.get(i);
			if (!entry.isEclipseRuntimeRequired()) {
				urls.add(entry.getEntryURL());
			}
		}
		return urls.toArray(new URL[urls.size()]);
	}

	/**
	 * Returns the entire set of URLs that define the Ant runtime classpath. Includes the Ant URLs, the additional URLs and extra classpath URLs.
	 * 
	 * @return the entire runtime classpath of URLs
	 */
	public URL[] getURLs() {
		List<URL> result = new ArrayList<>(60);
		if (antHomeEntries != null) {
			addEntryURLs(result, antHomeEntries);
		}
		if (additionalEntries != null && additionalEntries.length > 0) {
			addEntryURLs(result, additionalEntries);
		}

		for (int i = 0; i < extraClasspathURLs.size(); i++) {
			IAntClasspathEntry entry = extraClasspathURLs.get(i);
			URL url = entry.getEntryURL();
			if (url != null) {
				result.add(url);
			}
		}

		return result.toArray(new URL[result.size()]);
	}

	private void addEntryURLs(List<URL> result, IAntClasspathEntry[] entries) {
		for (int i = 0; i < entries.length; i++) {
			IAntClasspathEntry entry = entries[i];
			URL url = entry.getEntryURL();
			if (url != null) {
				result.add(url);
			}
		}
	}

	protected ClassLoader[] getPluginClassLoaders() {
		if (orderedPluginClassLoaders == null) {
			Iterator<WrappedClassLoader> classLoaders = pluginClassLoaders.iterator();
			Map<String, WrappedClassLoader> idToLoader = new HashMap<>(pluginClassLoaders.size());
			List<BundleRevision> bundles = new ArrayList<>(pluginClassLoaders.size());
			while (classLoaders.hasNext()) {
				WrappedClassLoader loader = classLoaders.next();
				idToLoader.put(loader.bundle.getSymbolicName(), loader);
				BundleRevision revision = loader.bundle.adapt(BundleRevision.class);
				if (revision != null) {
					bundles.add(revision);
				}
			}
			List<BundleRevision> sorted = computePrerequisiteOrder(bundles);
			List<WrappedClassLoader> loaders = new ArrayList<>(sorted.size());
			for (BundleRevision revision : sorted) {
				String id = revision.getSymbolicName();
				loaders.add(idToLoader.get(id));
			}
			orderedPluginClassLoaders = loaders.toArray(new ClassLoader[loaders.size()]);
		}
		return orderedPluginClassLoaders;
	}

	/*
	 * Copied from org.eclipse.pde.internal.build.Utils
	 */
	private List<BundleRevision> computePrerequisiteOrder(List<BundleRevision> plugins) {
		List<Relation> prereqs = new ArrayList<>(plugins.size());
		List<BundleRevision> fragments = new ArrayList<>();

		// create a collection of directed edges from plugin to prereq
		for (BundleRevision current : plugins) {
			if ((current.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
				fragments.add(current);
				continue;
			}
			boolean found = false;

			BundleRevision[] prereqList = getDependentBundles(current);
			for (BundleRevision prereq : prereqList) {
				// ensure that we only include values from the original set.
				if (plugins.contains(prereq)) {
					found = true;
					prereqs.add(new Relation(current, prereq));
				}
			}

			// if we didn't find any prereqs for this plugin, add a null prereq
			// to ensure the value is in the output
			if (!found) {
				prereqs.add(new Relation(current, null));
			}
		}

		// The fragments needs to added relatively to their host and to their
		// own prerequisite (bug #43244)
		for (BundleRevision currentFrag : fragments) {

			if (plugins.contains(currentFrag)) {
				BundleWiring wiring = currentFrag.getWiring();
				List<BundleWire> hostWires = wiring == null ? Collections.<BundleWire> emptyList()
						: wiring.getRequiredWires(HostNamespace.HOST_NAMESPACE);
				if (!hostWires.isEmpty()) {
					prereqs.add(new Relation(currentFrag, hostWires.get(0).getProvider()));
				}
			} else {
				AntCorePlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, AntCorePlugin.PI_ANTCORE, AntCorePlugin.ERROR_MALFORMED_URL, NLS.bind(InternalCoreAntMessages.AntCorePreferences_1, new String[] {
						currentFrag.getSymbolicName() }), null));
			}
		}

		// do a topological sort, insert the fragments into the sorted elements
		return computeNodeOrder(prereqs);
	}

	/*
	 * Copied from org.eclipse.pde.internal.build.site.PDEState.
	 */
	private BundleRevision[] getDependentBundles(BundleRevision root) {
		BundleRevision[] imported = getImportedBundles(root);
		BundleRevision[] required = getRequiredBundles(root);
		BundleRevision[] dependents = new BundleRevision[imported.length + required.length];
		System.arraycopy(imported, 0, dependents, 0, imported.length);
		System.arraycopy(required, 0, dependents, imported.length, required.length);
		return dependents;
	}

	/*
	 * Copied from org.eclipse.pde.internal.build.site.PDEState.
	 */
	private BundleRevision[] getRequiredBundles(BundleRevision root) {
		return getDependantRequirements(root, BundleNamespace.BUNDLE_NAMESPACE);
	}

	/*
	 * Copied from org.eclipse.pde.internal.build.site.PDEState.
	 */
	private BundleRevision[] getImportedBundles(BundleRevision root) {
		return getDependantRequirements(root, PackageNamespace.PACKAGE_NAMESPACE);
	}

	private BundleRevision[] getDependantRequirements(BundleRevision root, String namespace) {
		if (root == null) {
			return new BundleRevision[0];
		}
		BundleWiring wiring = root.getWiring();
		List<BundleWire> requiredWires = wiring == null ? Collections.<BundleWire> emptyList() : wiring.getRequiredWires(namespace);
		ArrayList<BundleRevision> requirementProviders = new ArrayList<>(requiredWires.size());
		for (BundleWire requiredWire : requiredWires) {
			BundleRevision provider = requiredWire.getProvider();
			if (!provider.equals(root) && !requirementProviders.contains(provider)) {
				requirementProviders.add(provider);
			}
		}
		return requirementProviders.toArray(new BundleRevision[requirementProviders.size()]);
	}

	/*
	 * Copied from org.eclipse.pde.internal.build.Utils
	 */
	private void removeArcs(List<Relation> edges, List<BundleRevision> roots, Map<BundleRevision, Integer> counts) {
		for (Iterator<BundleRevision> j = roots.iterator(); j.hasNext();) {
			Object root = j.next();
			for (int i = 0; i < edges.size(); i++) {
				if (root.equals(edges.get(i).to)) {
					BundleRevision input = edges.get(i).from;
					Integer count = counts.get(input);
					if (count != null) {
						counts.put(input, Integer.valueOf(count.intValue() - 1));
					}
				}
			}
		}
	}

	/*
	 * Copied from org.eclipse.pde.internal.build.Utils
	 */
	private List<BundleRevision> computeNodeOrder(List<Relation> edges) {
		Map<BundleRevision, Integer> counts = computeCounts(edges);
		List<BundleRevision> nodes = new ArrayList<>(counts.size());
		while (!counts.isEmpty()) {
			List<BundleRevision> roots = findRootNodes(counts);
			if (roots.isEmpty()) {
				break;
			}
			for (Iterator<BundleRevision> i = roots.iterator(); i.hasNext();) {
				counts.remove(i.next());
			}
			nodes.addAll(roots);
			removeArcs(edges, roots, counts);
		}
		return nodes;
	}

	/*
	 * Copied from org.eclipse.pde.internal.build.Utils
	 */
	private Map<BundleRevision, Integer> computeCounts(List<Relation> mappings) {
		Map<BundleRevision, Integer> counts = new HashMap<>(5);
		for (int i = 0; i < mappings.size(); i++) {
			BundleRevision from = mappings.get(i).from;
			Integer fromCount = counts.get(from);
			BundleRevision to = mappings.get(i).to;
			if (to == null)
				counts.put(from, Integer.valueOf(0));
			else {
				if (counts.get(to) == null)
					counts.put(to, Integer.valueOf(0));
				fromCount = fromCount == null ? Integer.valueOf(1) : new Integer(fromCount.intValue() + 1);
				counts.put(from, fromCount);
			}
		}
		return counts;
	}

	/*
	 * Copied from org.eclipse.pde.internal.build.Utils
	 */
	private List<BundleRevision> findRootNodes(Map<BundleRevision, Integer> counts) {
		List<BundleRevision> result = new ArrayList<>(5);
		for (Iterator<BundleRevision> i = counts.keySet().iterator(); i.hasNext();) {
			BundleRevision node = i.next();
			int count = counts.get(node).intValue();
			if (count == 0) {
				result.add(node);
			}
		}
		return result;
	}

	private void initializePluginClassLoaders() {
		pluginClassLoaders = new ArrayList<>(10);
		// ant.core should always be present
		pluginClassLoaders.add(getClassLoader(AntCorePlugin.getPlugin().getBundle()));
	}

	/**
	 * Returns the default and custom tasks.
	 * 
	 * @return the list of default and custom tasks.
	 */
	public List<Task> getTasks() {
		List<Task> result = new ArrayList<>(10);
		if (defaultTasks != null && !defaultTasks.isEmpty()) {
			result.addAll(defaultTasks);
		}
		if (customTasks != null && customTasks.length != 0) {
			result.addAll(Arrays.asList(customTasks));
		}
		return result;
	}

	/**
	 * Returns the default and custom tasks that are relevant when there is no Eclipse runtime context (an Ant build in a separate VM).
	 * 
	 * @return the list of default and custom tasks.
	 */
	public List<Task> getRemoteTasks() {
		List<Task> result = new ArrayList<>(10);
		if (defaultTasks != null && !defaultTasks.isEmpty()) {
			Iterator<Task> iter = defaultTasks.iterator();
			while (iter.hasNext()) {
				Task task = iter.next();
				if (!task.isEclipseRuntimeRequired()) {
					result.add(task);
				}
			}
		}
		if (customTasks != null && customTasks.length != 0) {
			result.addAll(Arrays.asList(customTasks));
		}
		return result;
	}

	/**
	 * Returns the user defined custom tasks
	 * 
	 * @return the user defined tasks
	 */
	public Task[] getCustomTasks() {
		return customTasks;
	}

	/**
	 * Returns the user defined custom types
	 * 
	 * @return the user defined types
	 */
	public Type[] getCustomTypes() {
		return customTypes;
	}

	/**
	 * Returns the custom user properties specified for Ant builds.
	 * 
	 * @return the properties defined for Ant builds.
	 */
	public Property[] getCustomProperties() {
		return customProperties;
	}

	/**
	 * Returns the default and custom properties.
	 * 
	 * @return the list of default and custom properties.
	 * @since 3.0
	 */
	public List<Property> getProperties() {
		List<Property> result = new ArrayList<>(10);
		if (defaultProperties != null && !defaultProperties.isEmpty()) {
			result.addAll(defaultProperties);
		}
		if (customProperties != null && customProperties.length != 0) {
			result.addAll(Arrays.asList(customProperties));
		}
		return result;
	}

	/**
	 * Returns the default and custom properties that are relevant when there is no Eclipse runtime context (Ant build in a separate VM).
	 * 
	 * @return the list of default and custom properties.
	 * @since 3.0
	 */
	public List<Property> getRemoteAntProperties() {
		List<Property> result = new ArrayList<>(10);
		if (defaultProperties != null && !defaultProperties.isEmpty()) {
			Iterator<Property> iter = defaultProperties.iterator();
			while (iter.hasNext()) {
				Property property = iter.next();
				if (!property.isEclipseRuntimeRequired()) {
					result.add(property);
				}
			}
		}
		if (customProperties != null && customProperties.length != 0) {
			result.addAll(Arrays.asList(customProperties));
		}
		return result;
	}

	/**
	 * Returns the custom property files specified for Ant builds performing any required string substitution if indicated.
	 * 
	 * @param performStringSubstition
	 *            whether or not to perform the string substitution on the property file strings
	 * @return the property files defined for Ant builds.
	 * @since 3.0
	 */
	public String[] getCustomPropertyFiles(boolean performStringSubstition) {
		if (!performStringSubstition || customPropertyFiles == null || customPropertyFiles.length == 0) {
			return customPropertyFiles;
		}
		List<String> files = new ArrayList<>(customPropertyFiles.length);
		for (int i = 0; i < customPropertyFiles.length; i++) {
			String filename = customPropertyFiles[i];
			try {
				filename = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(filename);
				files.add(filename);
			}
			catch (CoreException e) {
				// notify the user via the Ant console of the missing file
				files.add(filename);
			}
		}
		return files.toArray(new String[files.size()]);
	}

	/**
	 * Returns the custom property files specified for Ant builds.
	 * 
	 * @return the property files defined for Ant builds.
	 */
	public String[] getCustomPropertyFiles() {
		return getCustomPropertyFiles(true);
	}

	/**
	 * Returns the custom URLs specified for the Ant classpath
	 * 
	 * @return the URLs defining the Ant classpath
	 * @deprecated
	 */
	@Deprecated
	public URL[] getCustomURLs() {
		URL[] urls = new URL[additionalEntries.length];
		int i;
		for (i = 0; i < additionalEntries.length; i++) {
			URL url = additionalEntries[i].getEntryURL();
			if (url != null) {
				urls[i] = url;
			}
		}

		return urls;
	}

	/**
	 * Sets the user defined custom tasks. To commit the changes, updatePluginPreferences must be called.
	 * 
	 * @param tasks
	 */
	public void setCustomTasks(Task[] tasks) {
		oldCustomTasks = customTasks;
		customTasks = tasks;
	}

	/**
	 * Sets the user defined custom types. To commit the changes, updatePluginPreferences must be called.
	 * 
	 * @param types
	 *            The custom types
	 */
	public void setCustomTypes(Type[] types) {
		oldCustomTypes = customTypes;
		customTypes = types;
	}

	/**
	 * Sets the custom URLs specified for the Ant classpath. To commit the changes, updatePluginPreferences must be called.
	 * 
	 * @param urls
	 *            the URLs defining the Ant classpath
	 * @deprecated use setAdditionalEntries(IAntClasspathEntry)[]
	 */
	@Deprecated
	public void setCustomURLs(URL[] urls) {
		additionalEntries = new IAntClasspathEntry[urls.length];
		for (int i = 0; i < urls.length; i++) {
			URL url = urls[i];
			IAntClasspathEntry entry = new AntClasspathEntry(url);
			additionalEntries[i] = entry;
		}
	}

	/**
	 * Sets the Ant URLs specified for the Ant classpath. To commit the changes, updatePluginPreferences must be called.
	 * 
	 * @param urls
	 *            the URLs defining the Ant classpath
	 * @deprecated use setAntHomeEntires(IAntClasspathEntry[])
	 */
	@Deprecated
	public void setAntURLs(URL[] urls) {
		antHomeEntries = new IAntClasspathEntry[urls.length];
		for (int i = 0; i < urls.length; i++) {
			URL url = urls[i];
			IAntClasspathEntry entry = new AntClasspathEntry(url);
			antHomeEntries[i] = entry;
		}
	}

	/**
	 * Sets the custom property files specified for Ant builds. To commit the changes, updatePluginPreferences must be called.
	 * 
	 * @param paths
	 *            the absolute paths defining the property files to use.
	 */
	public void setCustomPropertyFiles(String[] paths) {
		customPropertyFiles = paths;
	}

	/**
	 * Sets the custom user properties specified for Ant builds. To commit the changes, updatePluginPreferences must be called.
	 * 
	 * @param properties
	 *            the properties defining the Ant properties
	 */
	public void setCustomProperties(Property[] properties) {
		oldCustomProperties = customProperties;
		customProperties = properties;
	}

	/**
	 * Returns the default and custom types.
	 * 
	 * @return all of the defined types
	 */
	public List<Type> getTypes() {
		List<Type> result = new ArrayList<>(10);
		if (defaultTypes != null && !defaultTypes.isEmpty()) {
			result.addAll(defaultTypes);
		}
		if (customTypes != null && customTypes.length != 0) {
			result.addAll(Arrays.asList(customTypes));
		}
		return result;
	}

	/**
	 * Returns the default and custom types that are relevant when there is no Eclipse runtime context (an Ant build in a separate VM).
	 * 
	 * @return the list of default and custom types.
	 */
	public List<Type> getRemoteTypes() {
		List<Type> result = new ArrayList<>(10);
		if (defaultTypes != null && !defaultTypes.isEmpty()) {
			Iterator<Type> iter = defaultTypes.iterator();
			while (iter.hasNext()) {
				Type type = iter.next();
				if (!type.isEclipseRuntimeRequired()) {
					result.add(type);
				}
			}
		}
		if (customTypes != null && customTypes.length != 0) {
			result.addAll(Arrays.asList(customTypes));
		}
		return result;
	}

	/**
	 * Returns the default types defined via the type extension point
	 * 
	 * @return all of the default types
	 */
	public List<Type> getDefaultTypes() {
		List<Type> result = new ArrayList<>(10);
		if (defaultTypes != null && !defaultTypes.isEmpty()) {
			result.addAll(defaultTypes);
		}
		return result;
	}

	/**
	 * Returns the default tasks defined via the task extension point
	 * 
	 * @return all of the default tasks
	 */
	public List<Task> getDefaultTasks() {
		List<Task> result = new ArrayList<>(10);
		if (defaultTasks != null && !defaultTasks.isEmpty()) {
			result.addAll(defaultTasks);
		}
		return result;
	}

	/**
	 * Returns the default properties defined via the properties extension point
	 * 
	 * @return all of the default properties
	 * @since 3.0
	 */
	public List<Property> getDefaultProperties() {
		List<Property> result = new ArrayList<>(10);
		if (defaultProperties != null && !defaultProperties.isEmpty()) {
			result.addAll(defaultProperties);
		}
		return result;
	}

	/*
	 * Convert a list of tokens into an array using "," as the tokenizer.
	 */
	protected String[] getArrayFromString(String list) {
		String separator = ","; //$NON-NLS-1$
		if (list == null || list.trim().equals(IAntCoreConstants.EMPTY_STRING)) {
			return new String[0];
		}
		ArrayList<String> result = new ArrayList<>();
		for (StringTokenizer tokens = new StringTokenizer(list, separator); tokens.hasMoreTokens();) {
			String token = tokens.nextToken().trim();
			if (!token.equals(IAntCoreConstants.EMPTY_STRING)) {
				result.add(token);
			}
		}
		return result.toArray(new String[result.size()]);
	}

	/**
	 * Updates the underlying plug-in preferences to the current state.
	 */
	public void updatePluginPreferences() {
		IEclipsePreferences node = InstanceScope.INSTANCE.getNode(AntCorePlugin.PI_ANTCORE);
		if (node != null) {
			node.removePreferenceChangeListener(prefListener);
			Preferences prefs = AntCorePlugin.getPlugin().getPluginPreferences();
			updateTasks(prefs);
			updateTypes(prefs);
			updateAntHomeEntries(prefs);
			updateAdditionalEntries(prefs);
			updateProperties(prefs);
			updatePropertyFiles(prefs);
			boolean classpathChanged = AntCorePlugin.getPlugin().getPluginPreferences().needsSaving();
			AntCorePlugin.getPlugin().savePluginPreferences();
			if (classpathChanged) {
				prefs.setValue(IAntCoreConstants.PREFERENCE_CLASSPATH_CHANGED, true);
			}
			prefs.setValue(IAntCoreConstants.PREFERENCE_CLASSPATH_CHANGED, false);
			node.addPreferenceChangeListener(prefListener);
		}

	}

	protected void updateTasks(Preferences prefs) {
		if (oldCustomTasks != null) {
			for (int i = 0; i < oldCustomTasks.length; i++) {
				Task oldTask = oldCustomTasks[i];
				prefs.setToDefault(IAntCoreConstants.PREFIX_TASK + oldTask.getTaskName());
			}
			oldCustomTasks = null;
		}

		if (customTasks.length == 0) {
			prefs.setValue(IAntCoreConstants.PREFERENCE_TASKS, IAntCoreConstants.EMPTY_STRING);
			return;
		}
		StringBuffer tasks = new StringBuffer();
		for (int i = 0; i < customTasks.length; i++) {
			tasks.append(customTasks[i].getTaskName());
			tasks.append(',');
			prefs.setValue(IAntCoreConstants.PREFIX_TASK + customTasks[i].getTaskName(), customTasks[i].getClassName() + "," //$NON-NLS-1$
					+ customTasks[i].getLibraryEntry().getLabel());
		}
		prefs.setValue(IAntCoreConstants.PREFERENCE_TASKS, tasks.toString());
	}

	protected void updateTypes(Preferences prefs) {
		if (oldCustomTypes != null) {
			for (int i = 0; i < oldCustomTypes.length; i++) {
				Type oldType = oldCustomTypes[i];
				prefs.setToDefault(IAntCoreConstants.PREFIX_TYPE + oldType.getTypeName());
			}
			oldCustomTypes = null;
		}

		if (customTypes.length == 0) {
			prefs.setValue(IAntCoreConstants.PREFERENCE_TYPES, IAntCoreConstants.EMPTY_STRING);
			return;
		}
		StringBuffer types = new StringBuffer();
		for (int i = 0; i < customTypes.length; i++) {
			types.append(customTypes[i].getTypeName());
			types.append(',');
			prefs.setValue(IAntCoreConstants.PREFIX_TYPE + customTypes[i].getTypeName(), customTypes[i].getClassName() + "," //$NON-NLS-1$
					+ customTypes[i].getLibraryEntry().getLabel());
		}
		prefs.setValue(IAntCoreConstants.PREFERENCE_TYPES, types.toString());
	}

	protected void updateProperties(Preferences prefs) {
		if (oldCustomProperties != null) {
			for (int i = 0; i < oldCustomProperties.length; i++) {
				Property oldProperty = oldCustomProperties[i];
				prefs.setToDefault(IAntCoreConstants.PREFIX_PROPERTY + oldProperty.getName());
			}
			oldCustomProperties = null;
		}

		if (customProperties.length == 0) {
			prefs.setValue(IAntCoreConstants.PREFERENCE_PROPERTIES, IAntCoreConstants.EMPTY_STRING);
			return;
		}
		StringBuffer properties = new StringBuffer();
		for (int i = 0; i < customProperties.length; i++) {
			properties.append(customProperties[i].getName());
			properties.append(',');
			prefs.setValue(IAntCoreConstants.PREFIX_PROPERTY + customProperties[i].getName(), customProperties[i].getValue(false));
		}
		prefs.setValue(IAntCoreConstants.PREFERENCE_PROPERTIES, properties.toString());
	}

	protected void updateAdditionalEntries(Preferences prefs) {
		prefs.setValue("urls", IAntCoreConstants.EMPTY_STRING); // old constant removed //$NON-NLS-1$
		String serialized = IAntCoreConstants.EMPTY_STRING;
		IAntClasspathEntry toolsJarEntry = getToolsJarEntry();
		List<IAntClasspathEntry> userLibs = getUserLibraries();
		if (userLibs == null) {
			userLibs = new ArrayList<>();
		}
		if (toolsJarEntry != null) {
			userLibs.add(toolsJarEntry);
		}
		boolean changed = true;
		if (additionalEntries.length == userLibs.size()) {
			changed = false;
			for (int i = 0; i < additionalEntries.length; i++) {
				if (!additionalEntries[i].equals(userLibs.get(i))) {
					changed = true;
					break;
				}
			}
		}
		if (changed) {
			StringBuffer entries = new StringBuffer();
			for (int i = 0; i < additionalEntries.length; i++) {
				entries.append(additionalEntries[i].getLabel());
				entries.append(',');
			}
			serialized = entries.toString();
		}

		prefs.setValue(IAntCoreConstants.PREFERENCE_ADDITIONAL_ENTRIES, serialized);

		String prefAntHome = IAntCoreConstants.EMPTY_STRING;
		if (antHome != null && !antHome.equals(getDefaultAntHome())) {
			prefAntHome = antHome;
		}
		prefs.setValue(IAntCoreConstants.PREFERENCE_ANT_HOME, prefAntHome);
	}

	protected void updateAntHomeEntries(Preferences prefs) {
		prefs.setValue("ant_urls", IAntCoreConstants.EMPTY_STRING); // old constant removed //$NON-NLS-1$

		// see if the custom entries are just the default entries
		IAntClasspathEntry[] defaultEntries = getDefaultAntHomeEntries();
		boolean dflt = false;
		if (defaultEntries.length == antHomeEntries.length) {
			dflt = true;
			for (int i = 0; i < antHomeEntries.length; i++) {
				if (!antHomeEntries[i].equals(defaultEntries[i])) {
					dflt = false;
					break;
				}
			}
		}
		if (dflt) {
			// always want to recalculate the default Ant urls
			// to pick up any changes in the default Ant classpath
			prefs.setValue(IAntCoreConstants.PREFERENCE_ANT_HOME_ENTRIES, IAntCoreConstants.EMPTY_STRING);
			return;
		}
		StringBuffer entries = new StringBuffer();
		for (int i = 0; i < antHomeEntries.length; i++) {
			entries.append(antHomeEntries[i].getLabel());
			entries.append(',');
		}

		prefs.setValue(IAntCoreConstants.PREFERENCE_ANT_HOME_ENTRIES, entries.toString());
	}

	protected void updatePropertyFiles(Preferences prefs) {
		StringBuffer files = new StringBuffer();
		for (int i = 0; i < customPropertyFiles.length; i++) {
			files.append(customPropertyFiles[i]);
			files.append(',');
		}

		prefs.setValue(IAntCoreConstants.PREFERENCE_PROPERTY_FILES, files.toString());
	}

	/**
	 * Sets the string that defines the Ant home set by the user. May be set to <code>null</code>.
	 * 
	 * @param antHome
	 *            the fully qualified path to Ant home
	 */
	public void setAntHome(String antHome) {
		this.antHome = antHome;
	}

	/**
	 * Returns the string that defines the Ant home set by the user or the location of the Eclipse Ant plug-in if Ant home has not been specifically
	 * set by the user. Can return <code>null</code>
	 * 
	 * @return the fully qualified path to Ant home
	 */
	public String getAntHome() {
		return antHome;
	}

	/**
	 * Returns the set of classpath entries that compose the libraries added to the Ant runtime classpath from the Ant home location.
	 * 
	 * @return the set of ant home classpath entries
	 * @since 3.0
	 */
	public IAntClasspathEntry[] getAntHomeClasspathEntries() {
		return antHomeEntries;
	}

	/**
	 * Returns the set of classpath entries that the user has added to the Ant runtime classpath.
	 * 
	 * @return the set of user classpath entries
	 * @since 3.0
	 */
	public IAntClasspathEntry[] getAdditionalClasspathEntries() {
		return additionalEntries;
	}

	/**
	 * Sets the set of classpath entries that compose the libraries added to the Ant runtime classpath from the Ant home location.
	 * 
	 * @param entries
	 *            the set of ant home classpath entries
	 * @since 3.0
	 */
	public void setAntHomeClasspathEntries(IAntClasspathEntry[] entries) {
		antHomeEntries = entries;
	}

	/**
	 * Sets the set of classpath entries that the user has added to the Ant runtime classpath.
	 * 
	 * @param entries
	 *            the set of user classpath entries
	 * @since 3.0
	 */
	public void setAdditionalClasspathEntries(IAntClasspathEntry[] entries) {
		additionalEntries = entries;
	}

	/**
	 * Returns the list of URLs to added to the classpath for an Ant build that is occurring without the Eclipse runtime.
	 * 
	 * @return the list of classpath entries
	 * @since 3.0
	 */
	public URL[] getRemoteAntURLs() {
		List<URL> result = new ArrayList<>(40);
		if (antHomeEntries != null) {
			for (int i = 0; i < antHomeEntries.length; i++) {
				IAntClasspathEntry entry = antHomeEntries[i];
				result.add(entry.getEntryURL());
			}
		}
		if (additionalEntries != null && additionalEntries.length > 0) {
			for (int i = 0; i < additionalEntries.length; i++) {
				IAntClasspathEntry entry = additionalEntries[i];
				result.add(entry.getEntryURL());
			}
		}
		if (extraClasspathURLs != null) {
			for (int i = 0; i < extraClasspathURLs.size(); i++) {
				IAntClasspathEntry entry = extraClasspathURLs.get(i);
				if (!entry.isEclipseRuntimeRequired()) {
					result.add(entry.getEntryURL());
				}
			}
		}

		return result.toArray(new URL[result.size()]);
	}

	/**
	 * Returns all contributed classpath entries via the <code>extraClasspathEntries</code> extension point.
	 * 
	 * @return all contributed classpath entries via the <code>extraClasspathEntries</code> extension point
	 * @since 3.0
	 */
	public IAntClasspathEntry[] getContributedClasspathEntries() {
		return extraClasspathURLs.toArray(new IAntClasspathEntry[extraClasspathURLs.size()]);
	}
}
