/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * 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));
				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, new Integer(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, new Integer(0));
			else {
				if (counts.get(to) == null)
					counts.put(to, new Integer(0));
				fromCount = fromCount == null ? new Integer(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()]);
	}
}
