/*******************************************************************************
 * Copyright (c) 2000, 2013 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<AntClasspathEntry>(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<AntClasspathEntry>(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[0].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<Task>(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<Type>(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<URL>(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<Object, Object>(AntCorePlugin.getPlugin().getBundle().getBundleContext(), PackageAdmin.class.getName(), null);
			tracker.open();
			try {
				List<AntClasspathEntry> result = new ArrayList<AntClasspathEntry>(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<Bundle>();
		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<Task>(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<Type>(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<Property>(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<IAntClasspathEntry>(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<URL>(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<URL>(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<String, WrappedClassLoader>(pluginClassLoaders.size());
			List<BundleRevision> bundles = new ArrayList<BundleRevision>(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<WrappedClassLoader>(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<Relation>(plugins.size());
		List<BundleRevision> fragments = new ArrayList<BundleRevision>();

		// 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<BundleRevision>(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<BundleRevision>(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<BundleRevision, Integer>(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<BundleRevision>(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<WrappedClassLoader>(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<Task>(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<Task>(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<Property>(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<Property>(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<String>(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<Type>(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<Type>(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<Type>(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<Task>(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<Property>(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<String>();
		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()
					+ "," + customTasks[i].getLibraryEntry().getLabel()); //$NON-NLS-1$
		}
		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()
					+ "," + customTypes[i].getLibraryEntry().getLabel()); //$NON-NLS-1$
		}
		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<IAntClasspathEntry>();
		}
		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<URL>(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()]);
	}
}
