/*******************************************************************************
 * Copyright (c) 2005, 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
 *
 *******************************************************************************/
package org.eclipse.dltk.launching;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IBuildpathAttribute;
import org.eclipse.dltk.core.IBuildpathContainer;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IScriptModel;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.environment.EnvironmentManager;
import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.dltk.core.environment.IEnvironment;
import org.eclipse.dltk.core.environment.IFileHandle;
import org.eclipse.dltk.core.internal.environment.LocalEnvironment;
import org.eclipse.dltk.internal.launching.CompositeId;
import org.eclipse.dltk.internal.launching.DLTKLaunchingPlugin;
import org.eclipse.dltk.internal.launching.DefaultEntryResolver;
import org.eclipse.dltk.internal.launching.DefaultProjectBuildpathEntry;
import org.eclipse.dltk.internal.launching.InterpreterContainerInitializer;
import org.eclipse.dltk.internal.launching.InterpreterDefinitionsContainer;
import org.eclipse.dltk.internal.launching.InterpreterListener;
import org.eclipse.dltk.internal.launching.RuntimeBuildpathEntry;
import org.eclipse.dltk.internal.launching.RuntimeBuildpathEntryResolver;
import org.eclipse.dltk.internal.launching.RuntimeBuildpathProvider;
import org.eclipse.dltk.internal.launching.ScriptSourceLookupUtil;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.osgi.service.prefs.BackingStoreException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.ibm.icu.text.MessageFormat;

/**
 * The central access point for launching support. This class manages the
 * registered interpreters types contributed through the
 * <code>"org.eclipse.dltk.launching.interpreterType"</code> extension point. As
 * well, this class provides interpreter install change notification, and
 * computes buildpaths and source lookup paths for launch configurations.
 * <p>
 * This class provides static methods only; it is not intended to be
 * instantiated or subclassed by clients.
 * </p>
 */
public final class ScriptRuntime {

	/**
	 * Classpath container used for a project's InterpreterEnvironment (value
	 * <code>"org.eclipse.dltk.launching.INTERPRETER_CONTAINER"</code> ). A
	 * container is resolved in the context of a specific Script project, to one
	 * or more system libraries contained in a InterpreterEnvironment. The
	 * container can have zero or two path segments following the container
	 * name. When no segments follow the container name, the workspace default
	 * InterpreterEnvironment is used to build a project. Otherwise the segments
	 * identify a specific InterpreterEnvironment used to build a project:
	 * <ol>
	 * <li>Interpreter Install Type Identifier - identifies the type of
	 * InterpreterEnvironment used to build the project. For example, the
	 * standard Interpreter.</li>
	 * <li>Interpreter Install Name - a user defined name that identifies that a
	 * specific Interpreter of the above kind. For example,
	 * <code>IBM 1.3.1</code>. This information is shared in a projects
	 * buildpath file, so teams must agree on InterpreterEnvironment naming
	 * conventions.</li>
	 * </ol>
	 * <p>
	 * The path may also identify an execution environment as follows:
	 * <ol>
	 * <li>Execution environment extension point name (value
	 * <code>executionEnvironments</code>)</li>
	 * <li>Identifier of a contributed execution environment</li>
	 * </ol>
	 * </p>
	 *
	 */
	public static final String INTERPRETER_CONTAINER = DLTKLaunchingPlugin
			.getUniqueIdentifier() + ".INTERPRETER_CONTAINER"; //$NON-NLS-1$

	/**
	 * Simple identifier constant (value
	 * <code>"runtimeBuildpathEntryResolvers"</code>) for the runtime buildpath
	 * entry resolvers extension point.
	 */
	public static final String EXTENSION_POINT_RUNTIME_BUILDPATH_ENTRY_RESOLVERS = "runtimeBuildpathEntryResolvers"; //$NON-NLS-1$

	/**
	 * Simple identifier constant (value <code>"buildpathProviders"</code>) for
	 * the runtime buildpath providers extension point.
	 */
	public static final String EXTENSION_POINT_RUNTIME_BUILDPATH_PROVIDERS = "buildpathProviders"; //$NON-NLS-1$

	/**
	 * Simple identifier constant (value <code>"interpreterInstalls"</code>) for
	 * the interpreters installs extension point.
	 */
	public static final String EXTENSION_POINT_INTERPRETER_INSTALLS = "interpreterInstalls"; //$NON-NLS-1$

	/**
	 * A status code indicating that a interpreter could not be resolved for a
	 * project. When a interpreter cannot be resolved for a project by this
	 * plug-in's container initializer, an exception is thrown with this status
	 * code. A status handler may be registered for this status code. The
	 * <code>source</code> object provided to the status handler is the script
	 * project for which the path could not be resolved. The status handler must
	 * return an <code>IInterpreterInstall</code> or <code>null</code>. The
	 * container resolver will re-set the project's buildpath if required.
	 */
	public static final int ERR_UNABLE_TO_RESOLVE_INTERPRETER = 160;

	/**
	 * Preference key for launch/connect timeout. Interpreter Runners should
	 * honor this timeout value when attempting to launch and connect to a
	 * debugger. The value is an int, indicating a number of milliseconds.
	 */
	public static final String PREF_CONNECT_TIMEOUT = DLTKLaunchingPlugin
			.getUniqueIdentifier() + ".PREF_CONNECT_TIMEOUT"; //$NON-NLS-1$

	/**
	 * Preference key for the String of XML that defines all installed
	 * Interpreters.
	 */
	public static final String PREF_INTERPRETER_XML = DLTKLaunchingPlugin
			.getUniqueIdentifier() + ".PREF_INTERPRETER_XML"; //$NON-NLS-1$

	/**
	 * Default launch/connect timeout (ms).
	 */
	public static final int DEF_CONNECT_TIMEOUT = 20000;

	/**
	 * Attribute key for a buildpath attribute referencing a list of shared
	 * libraries that should appear on the
	 * <code>-Dinterpreter.library.path</code> system property.
	 * <p>
	 * The factory methods <code>newLibraryPathsAttribute(String[])</code> and
	 * <code>getLibraryPaths(IBuildpathAttribute)</code> should be used to
	 * encode and decode the attribute value.
	 * </p>
	 * <p>
	 * Each string is used to create an <code>IPath</code> using the constructor
	 * <code>Path(String)</code>, and may contain <code>IStringVariable</code>
	 * 's. Variable substitution is performed on the string prior to
	 * constructing a path from the string. If the resulting <code>IPath</code>
	 * is a relative path, it is interpreted as relative to the workspace
	 * location. If the path is absolute, it is interpreted as an absolute path
	 * in the local file system.
	 * </p>
	 */
	public static final String BUILDPATH_ATTR_LIBRARY_PATH_ENTRY = DLTKLaunchingPlugin
			.getUniqueIdentifier() + ".CLASSPATH_ATTR_LIBRARY_PATH_ENTRY"; //$NON-NLS-1$

	// lock for interpreter initialization
	private static Object fgInterpreterLock = new Object();
	private static boolean fgInitializingInterpreters = false;

	private static IInterpreterInstallType[] fgInterpreterTypes = null;

	/**
	 * This class is deprecated in 5.0 and should not be used outside of DLTK
	 * core plugins. The affected APIs will be updated, e.g. see
	 * {@link ScriptRuntime#getDefaultInterpreterInstall(String, IEnvironment)}
	 */
	@Deprecated
	public static class DefaultInterpreterEntry {
		private final String nature;
		private final String environment;

		public DefaultInterpreterEntry(String nature, String environment) {
			this.nature = nature;
			this.environment = environment;
		}

		public String getNature() {
			return nature;
		}

		public String getEnvironment() {
			return environment;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result
					+ ((environment == null) ? 0 : environment.hashCode());
			result = prime * result
					+ ((nature == null) ? 0 : nature.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			DefaultInterpreterEntry other = (DefaultInterpreterEntry) obj;
			if (environment == null) {
				if (other.environment != null)
					return false;
			} else if (!environment.equals(other.environment))
				return false;
			if (nature == null) {
				if (other.nature != null)
					return false;
			} else if (!nature.equals(other.nature))
				return false;
			return true;
		}

		@Override
		public String toString() {
			return nature + "/" + environment; //$NON-NLS-1$
		}
	}

	/**
	 * Contain association of default interpreter entries to interprter
	 * identifiers.
	 */
	private static Map<DefaultInterpreterEntry, String> fgDefaultInterpreterId = new HashMap<>();

	/**
	 * Contain DefaultInterpreterEntry entry assocications
	 */
	private static Map<DefaultInterpreterEntry, String> fgDefaultInterpreterConnectorId = new HashMap<>();

	/**
	 * Resolvers keyed by variable name, container id, and runtime buildpath
	 * entry id.
	 */
	private static Map<String, IRuntimeBuildpathEntryResolver> fgContainerResolvers = null;
	private static Map<String, IRuntimeBuildpathEntryResolver> fgRuntimeBuildpathEntryResolvers = null;

	/**
	 * Path providers keyed by id
	 */
	private static Map<String, IRuntimeBuildpathProvider> fgPathProviders = null;

	/**
	 * Default buildpath and source path providers.
	 */
	private static IRuntimeBuildpathProvider fgDefaultBuildpathProvider = new StandardBuildpathProvider();
	private static IRuntimeBuildpathProvider fgDefaultSourcepathProvider = new StandardSourcepathProvider();

	/**
	 * Interpreter change listeners
	 */
	private static ListenerList<IInterpreterInstallChangedListener> fgInterpreterListeners = new ListenerList<>(
			ListenerList.IDENTITY);

	/**
	 * Cache of already resolved projects in container entries. Used to avoid
	 * cycles in project dependencies when resolving buildpath container
	 * entries. Counters used to know when entering/exiting to clear cache
	 */
	private static ThreadLocal<List<IScriptProject>> fgProjects = new ThreadLocal<>();
	private static ThreadLocal<Integer> fgEntryCount = new ThreadLocal<>();

	/**
	 * Set of IDs of Interpreters contributed via InterpreterInstalls extension
	 * point.
	 */
	private static Set<String> fgContributedInterpreters = new HashSet<>();

	/**
	 * This class contains only static methods, and is not intended to be
	 * instantiated.
	 */
	private ScriptRuntime() {
	}

	/**
	 * Initializes interpreter type extensions.
	 */
	private static void initializeInterpreterTypeExtensions() {
		IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
				.getExtensionPoint(DLTKLaunchingPlugin.PLUGIN_ID,
						"interpreterInstallTypes"); //$NON-NLS-1$
		IConfigurationElement[] configs = extensionPoint
				.getConfigurationElements();

		MultiStatus status = new MultiStatus(
				DLTKLaunchingPlugin.getUniqueIdentifier(), IStatus.OK,
				LaunchingMessages.ScriptRuntime_exceptionsOccurred, null);
		fgInterpreterTypes = new IInterpreterInstallType[configs.length];

		for (int i = 0; i < configs.length; i++) {
			try {
				IInterpreterInstallType installType = (IInterpreterInstallType) configs[i]
						.createExecutableExtension("class"); //$NON-NLS-1$
				fgInterpreterTypes[i] = installType;
			} catch (CoreException e) {
				status.add(e.getStatus());
			}
		}
		if (!status.isOK()) {
			// only happens on a CoreException
			DLTKLaunchingPlugin.log(status);
			// cleanup null entries in fgInterpreterTypes
			List<IInterpreterInstallType> temp = new ArrayList<>(
					fgInterpreterTypes.length);
			for (int i = 0; i < fgInterpreterTypes.length; i++) {
				if (fgInterpreterTypes[i] != null) {
					temp.add(fgInterpreterTypes[i]);
				}
				fgInterpreterTypes = temp
						.toArray(new IInterpreterInstallType[temp.size()]);
			}
		}
	}

	private static String getNatureFromProject(IScriptProject project) {
		try {
			IDLTKLanguageToolkit toolkit = DLTKLanguageManager
					.getLanguageToolkit(project);
			if (toolkit != null)
				return toolkit.getNatureId();
		} catch (Exception e) {
			DLTKLaunchingPlugin.log(e);
		}
		return null;
	}

	private static String getEnvironmentFromProject(IScriptProject project) {
		return EnvironmentManager.getEnvironmentId(project.getProject());
	}

	/**
	 * Returns the interpreter assigned to build the given script project. The
	 * project must exist. The interpreter assigned to a project is determined
	 * from its build path.
	 *
	 * @param project
	 *            the project to retrieve the interpreter from
	 * @return the interpreter instance that is assigned to build the given
	 *         script project Returns <code>null</code> if no interp. is
	 *         referenced on the project's build path.
	 * @throws CoreException
	 *             if unable to determine the project's interpreter install
	 */
	public static IInterpreterInstall getInterpreterInstall(
			IScriptProject project) throws CoreException {
		// check the buildpath
		IInterpreterInstall interpreter = null;

		IBuildpathEntry[] buildpath = project.getRawBuildpath();

		for (int i = 0; i < buildpath.length; i++) {
			IBuildpathEntry entry = buildpath[i];
			switch (entry.getEntryKind()) {
			case IBuildpathEntry.BPE_CONTAINER:
				IRuntimeBuildpathEntryResolver resolver = getContainerResolver(
						entry.getPath().segment(0));
				if (resolver != null) {
					interpreter = resolver.resolveInterpreterInstall(
							getNatureFromProject(project),
							getEnvironmentFromProject(project), entry);
				}
				break;
			}

			if (interpreter != null) {
				return interpreter;
			}
		}

		return null;
	}

	/**
	 * Returns the interpreter install type with the given unique id.
	 *
	 * @param id
	 *            the interpreter install type unique id
	 * @return The interpreter install type for the given id, or
	 *         <code>null</code> if no interpreter install type with the given
	 *         id is registered.
	 */
	public static IInterpreterInstallType getInterpreterInstallType(String id) {
		IInterpreterInstallType[] installTypes = getInterpreterInstallTypes();
		if (installTypes == null) {
			return null;
		}

		for (int i = 0; i < installTypes.length; i++) {
			IInterpreterInstallType type = installTypes[i];
			if (type != null && type.getId().equals(id)) {
				return type;
			}
		}

		return null;
	}

	/**
	 * Sets a Interpreter as the system-wide default Interpreter, and notifies
	 * registered Interpreter install change listeners of the change.
	 *
	 * @param interpreter
	 *            The Interpreter to make the default. May be <code>null</code>
	 *            to clear the default.
	 * @param monitor
	 *            progress monitor or <code>null</code>
	 */
	public static void setDefaultInterpreterInstall(
			IInterpreterInstall interpreter, IProgressMonitor monitor)
			throws CoreException {
		setDefaultInterpreterInstall(interpreter, monitor, true);
	}

	/**
	 * Sets a Interpreter as the nature default Interpreter, and notifies
	 * registered Interpreter install change listeners of the change.
	 *
	 * @param interpreter
	 *            The Interpreter to make the default. May be <code>null</code>
	 *            to clear the default.
	 * @param monitor
	 *            progress monitor or <code>null</code>
	 * @param savePreference
	 *            If <code>true</code>, update workbench preferences to reflect
	 *            the new default Interpreter.
	 *
	 */
	public static void setDefaultInterpreterInstall(
			IInterpreterInstall interpreter, IProgressMonitor monitor,
			boolean savePreference) throws CoreException {
		final IEnvironment env = interpreter.getEnvironment();
		if (env == null) {
			return;
		}
		final String environmentId = env.getId();
		IInterpreterInstall previous = null;
		String nature = interpreter.getInterpreterInstallType().getNatureId();

		DefaultInterpreterEntry defaultInterpreterID = new DefaultInterpreterEntry(
				nature, environmentId);
		if (fgDefaultInterpreterId.get(defaultInterpreterID) != null) {
			previous = getInterpreterFromCompositeId(
					fgDefaultInterpreterId.get(defaultInterpreterID));
		}
		fgDefaultInterpreterId.put(defaultInterpreterID,
				getCompositeIdFromInterpreter(interpreter));
		if (savePreference) {
			saveInterpreterConfiguration();
		}
		IInterpreterInstall current = null;
		if (fgDefaultInterpreterId.get(defaultInterpreterID) != null) {
			current = getInterpreterFromCompositeId(
					fgDefaultInterpreterId.get(defaultInterpreterID));
		}
		if (previous != current) {
			notifyDefaultInterpreterChanged(previous, current);
		}
	}

	/**
	 * Return the default interpreter set with
	 * <code>setDefaultInterpreter()</code> for the specified
	 * <code>natureId</code> and <code>environment</code> or <code>null</code>.
	 */
	public static IInterpreterInstall getDefaultInterpreterInstall(
			String natureId, IEnvironment environment) {
		return getDefaultInterpreterInstall(new DefaultInterpreterEntry(
				natureId, environment != null ? environment.getId()
						: LocalEnvironment.ENVIRONMENT_ID));
	}

	/**
	 * Return the default Interpreter set with
	 * <code>setDefaultInterpreter()</code>.
	 *
	 * @return Returns the default Interpreter.
	 */
	@Deprecated
	public static IInterpreterInstall getDefaultInterpreterInstall(
			DefaultInterpreterEntry entry) {
		IInterpreterInstall install = getInterpreterFromCompositeId(
				getDefaultInterpreterId(entry));
		if (install != null && install.getInstallLocation().exists()) {
			return install;
		}
		// if the default interp. goes missing, re-detect
		if (install != null) {
			// install.getInterpreterInstallType().disposeInterpreterInstall(
			// install.getId());
		}
		if (!hasInterpreterInstalls(entry.getNature(),
				entry.getEnvironment())) {
			/*
			 * If there are no any interpreters for the specified nature and
			 * environment - just return null and avoid re-initialization.
			 * Generally speaking user should not be forced to configure every
			 * interpreter for every host.
			 */
			return null;
		}
		synchronized (fgInterpreterLock) {
			// fgDefaultInterpreterId = null;
			fgDefaultInterpreterId.clear();
			fgInterpreterTypes = null;
			initializeInterpreters();
		}

		return getInterpreterFromCompositeId(getDefaultInterpreterId(entry));
	}

	/**
	 * Tests if there are any interpreters for the specified nature and host.
	 *
	 * @param natureId
	 * @param environmentId
	 * @return
	 */
	private static boolean hasInterpreterInstalls(String natureId,
			String environmentId) {
		if (environmentId == null) {
			return false;
		}
		for (IInterpreterInstallType type : getInterpreterInstallTypes(
				natureId)) {
			for (IInterpreterInstall install : type.getInterpreterInstalls()) {
				if (environmentId.equals(install.getEnvironmentId())) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Returns the list of registered interpreter types. Interpreter types are
	 * registered via <code>"org.eclipse.dltk.launching.interpreterTypes"</code>
	 * extension point. Returns an empty list if there are no registered
	 * interpreter types.
	 *
	 * @return the list of registered Interpreter types
	 */
	public static IInterpreterInstallType[] getInterpreterInstallTypes() {
		initializeInterpreters();
		return fgInterpreterTypes;
	}

	/**
	 * Returns FILTERED list of registered interpreter types. Interpreter types
	 * are registered via
	 * <code>"org.eclipse.dltk.launching.interpreterTypes"</code> extension
	 * point. Returns an empty list if there are no registered interpreter
	 * types.
	 *
	 * @return the list of registered Interpreter types
	 */
	public static IInterpreterInstallType[] getInterpreterInstallTypes(
			String nature) {
		List<IInterpreterInstallType> res = new ArrayList<>();
		synchronized (fgInterpreterLock) {
			initializeInterpreters();
			for (int i = 0; i < fgInterpreterTypes.length; i++) {
				IInterpreterInstallType t = fgInterpreterTypes[i];
				if (t.getNatureId().equals(nature))
					res.add(t);
			}
		}
		return res.toArray(new IInterpreterInstallType[res.size()]);
	}

	public static DefaultInterpreterEntry[] getDefaultInterpreterIDs() {
		Set<DefaultInterpreterEntry> set = fgDefaultInterpreterId.keySet();
		return set.toArray(new DefaultInterpreterEntry[set.size()]);
	}

	private static String getDefaultInterpreterId(
			DefaultInterpreterEntry entry) {
		initializeInterpreters();
		return fgDefaultInterpreterId.get(entry);
	}

	private static String getDefaultInterpreterConnectorId(
			DefaultInterpreterEntry entry) {
		initializeInterpreters();
		return fgDefaultInterpreterConnectorId.get(entry);
	}

	/**
	 * Returns a String that uniquely identifies the specified Interpreter
	 * across all Interpreter types.
	 *
	 * @param interpreter
	 *            the instance of IInterpreterInstallType to be identified
	 *
	 *
	 */
	public static String getCompositeIdFromInterpreter(
			IInterpreterInstall interpreter) {
		if (interpreter == null) {
			return null;
		}
		IInterpreterInstallType interpreterType = interpreter
				.getInterpreterInstallType();
		String typeID = interpreterType.getId();
		CompositeId id = new CompositeId(
				new String[] { typeID, interpreter.getId() });
		return id.toString();
	}

	/**
	 * Return the Interpreter corresponding to the specified composite Id. The
	 * id uniquely identifies a Interpreter across all Interpreter types.
	 *
	 * @param idString
	 *            the composite id that specifies an instance of
	 *            IInterpreterInstall
	 *
	 *
	 */
	public static IInterpreterInstall getInterpreterFromCompositeId(
			String idString) {
		if (idString == null || idString.length() == 0) {
			return null;
		}
		CompositeId id = CompositeId.fromString(idString);
		if (id.getPartCount() == 2) {
			IInterpreterInstallType InterpreterType = getInterpreterInstallType(
					id.get(0));
			if (InterpreterType != null) {
				return InterpreterType.findInterpreterInstall(id.get(1));
			}
		}
		return null;
	}

	/**
	 * Return the <code>IScriptProject</code> referenced in the specified
	 * configuration or <code>null</code> if none.
	 *
	 * @exception CoreException
	 *                if the referenced Script project does not exist
	 *
	 */
	public static IScriptProject getScriptProject(
			ILaunchConfiguration configuration) throws CoreException {
		String projectName = configuration.getAttribute(
				ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME,
				(String) null);
		if ((projectName == null) || (projectName.trim().length() < 1)) {
			return null;
		}
		IScriptProject scriptProject = getScriptModel()
				.getScriptProject(projectName);
		if (scriptProject != null && scriptProject.getProject().exists()
				&& !scriptProject.getProject().isOpen()) {
			abort(MessageFormat.format(LaunchingMessages.ScriptRuntime_28,
					configuration.getName(), projectName),
					ScriptLaunchConfigurationConstants.ERR_PROJECT_CLOSED,
					null);
		}
		if ((scriptProject == null) || !scriptProject.exists()) {
			abort(MessageFormat.format(
					LaunchingMessages.ScriptRuntime_Launch_configuration__0__references_non_existing_project__1___1,
					configuration.getName(), projectName),
					ScriptLaunchConfigurationConstants.ERR_NOT_A_SCRIPT_PROJECT,
					null);
		}
		return scriptProject;
	}

	/**
	 * Convenience method to get the script model.
	 */
	private static IScriptModel getScriptModel() {
		return DLTKCore.create(ResourcesPlugin.getWorkspace().getRoot());
	}

	/**
	 * Returns the Interpreter install for the given launch configuration. The
	 * Interpreter install is determined in the following prioritized way:
	 * <ol>
	 * <li>The Interpreter install is explicitly specified on the launch
	 * configuration via the <code>ATTR_CONTAINER_PATH</code> attribute.</li>
	 * <li>If no explicit Interpreter install is specified, the Interpreter
	 * install associated with the launch configuration's project is
	 * returned.</li>
	 * <li>If no project is specified, or the project does not specify a custom
	 * Interpreter install, the workspace default Interpreter install is
	 * returned.</li>
	 * </ol>
	 *
	 * @param configuration
	 *            launch configuration
	 * @return interpreter install
	 * @exception CoreException
	 *                if unable to compute a Interpreter install
	 *
	 */
	public static IInterpreterInstall computeInterpreterInstall(
			ILaunchConfiguration configuration) throws CoreException {
		// get field ATTR_NATURE from launch configuration
		String nature = configuration.getAttribute(
				ScriptLaunchConfigurationConstants.ATTR_SCRIPT_NATURE,
				(String) null);
		String containerPath = configuration.getAttribute(
				ScriptLaunchConfigurationConstants.ATTR_CONTAINER_PATH,
				(String) null);
		IScriptProject proj = getScriptProject(configuration);
		String environment = getEnvironmentFromProject(proj);
		if (containerPath == null) {
			if (proj != null) {
				IInterpreterInstall install = getInterpreterInstall(proj);
				if (install != null) {
					return install;
				}
				if (nature == null) {
					IDLTKLanguageToolkit tk = DLTKLanguageManager
							.getLanguageToolkit(proj);
					nature = tk.getNatureId();
				}
			}
		} else {
			IPath interpreterPath = Path.fromPortableString(containerPath);
			IBuildpathEntry entry = DLTKCore.newContainerEntry(interpreterPath);
			IRuntimeBuildpathEntryResolver2 resolver = getContainerResolver(
					interpreterPath.segment(0));
			if (resolver != null) {
				return resolver.resolveInterpreterInstall(nature, environment,
						entry);
			} else {
				resolver = getContainerResolver(interpreterPath.segment(0));
				if (resolver != null) {
					return resolver.resolveInterpreterInstall(nature,
							environment, entry);
				}
			}
		}

		if (nature == null) {
			abort(LaunchingMessages.ScriptRuntime_notDefaultInterpreter,
					ScriptLaunchConfigurationConstants.ERR_NO_DEFAULT_INTERPRETER_INSTALL,
					null);
		}
		// OR extract project nature from it's name (what about several
		// natures?)
		DefaultInterpreterEntry entry = new DefaultInterpreterEntry(nature,
				environment);
		IInterpreterInstall res = getDefaultInterpreterInstall(entry);
		if (res == null) {
			abort(LaunchingMessages.ScriptRuntime_notDefaultInterpreter,
					ScriptLaunchConfigurationConstants.ERR_NO_DEFAULT_INTERPRETER_INSTALL,
					null);
		}
		return res;
	}

	/**
	 * Throws a core exception with an internal error status.
	 *
	 * @param message
	 *            the status message
	 * @param exception
	 *            lower level exception associated with the error, or
	 *            <code>null</code> if none
	 */
	private static CoreException abort(String message, Throwable exception)
			throws CoreException {
		throw abort(message,
				ScriptLaunchConfigurationConstants.ERR_INTERNAL_ERROR,
				exception);
	}

	/**
	 * Throws a core exception with an internal error status.
	 *
	 * @param message
	 *            the status message
	 * @param code
	 *            status code
	 * @param exception
	 *            lower level exception associated with the
	 *
	 *            error, or <code>null</code> if none
	 */
	private static CoreException abort(String message, int code,
			Throwable exception) throws CoreException {
		throw new CoreException(new Status(IStatus.ERROR,
				DLTKLaunchingPlugin.PLUGIN_ID, code, message, exception));
	}

	/**
	 * Saves the Interpreter configuration information to the preferences. This
	 * includes the following information:
	 * <ul>
	 * <li>The list of all defined IInterpreterInstall instances.</li>
	 * <li>The default Interpreter</li>
	 * <ul>
	 * This state will be read again upon first access to Interpreter
	 * configuration information.
	 */
	public static void saveInterpreterConfiguration() throws CoreException {
		if (fgInterpreterTypes == null) {
			// if the Interpreter types have not been instantiated, there can be
			// no changes.
			return;
		}
		try {
			String xml = getInterpretersAsXML();
			getPreferences().put(PREF_INTERPRETER_XML, xml);
			savePreferences();
		} catch (IOException e) {
			throw new CoreException(new Status(IStatus.ERROR,
					DLTKLaunchingPlugin.getUniqueIdentifier(), IStatus.ERROR,
					LaunchingMessages.ScriptRuntime_exceptionsOccurred, e));
		} catch (ParserConfigurationException e) {
			throw new CoreException(new Status(IStatus.ERROR,
					DLTKLaunchingPlugin.getUniqueIdentifier(), IStatus.ERROR,
					LaunchingMessages.ScriptRuntime_exceptionsOccurred, e));
		} catch (TransformerException e) {
			throw new CoreException(new Status(IStatus.ERROR,
					DLTKLaunchingPlugin.getUniqueIdentifier(), IStatus.ERROR,
					LaunchingMessages.ScriptRuntime_exceptionsOccurred, e));
		}
	}

	private static String getInterpretersAsXML() throws IOException,
			ParserConfigurationException, TransformerException {
		InterpreterDefinitionsContainer container = new InterpreterDefinitionsContainer();

		DefaultInterpreterEntry[] entries = getDefaultInterpreterIDs();
		for (int i = 0; i < entries.length; i++) {
			String id = getDefaultInterpreterId(entries[i]);
			if (id != null)
				container.setDefaultInterpreterInstallCompositeID(entries[i],
						id);
			id = getDefaultInterpreterConnectorId(entries[i]);
			if (id != null)
				container.setDefaultInterpreterInstallConnectorTypeID(
						entries[i], id);
		}

		IInterpreterInstallType[] InterpreterTypes = getInterpreterInstallTypes();
		for (int i = 0; i < InterpreterTypes.length; ++i) {
			IInterpreterInstall[] Interpreters = InterpreterTypes[i]
					.getInterpreterInstalls();
			for (int j = 0; j < Interpreters.length; j++) {
				IInterpreterInstall install = Interpreters[j];
				container.addInterpreter(install);
			}
		}
		return container.getAsXML();
	}

	/**
	 * This method loads installed interpreters based an existing user
	 * preference or old Interpreter configurations file. The interpreters found
	 * in the preference or interpreter configurations file are added to the
	 * given Interpreter definitions container.
	 *
	 * Returns whether the user preferences should be set - i.e. if it was not
	 * already set when initialized.
	 */
	private static boolean addPersistedInterpreters(
			InterpreterDefinitionsContainer interpreterDefs) {
		// Try retrieving the interpreter preferences from the preference store
		String interpreterXMLString = getPreferences().get(PREF_INTERPRETER_XML,
				"");

		if (interpreterXMLString.length() == 0) {
			// default scope value could be specified in the
			// plugin_customization.ini file
			interpreterXMLString = DefaultScope.INSTANCE
					.getNode(DLTKLaunchingPlugin.PLUGIN_ID)
					.get(PREF_INTERPRETER_XML, "");
		}

		// If the preference was found, load interpreters from it into memory
		if (interpreterXMLString.length() > 0) {
			try {
				Reader inputStream = new StringReader(interpreterXMLString);
				InterpreterDefinitionsContainer
						.parseXMLIntoContainer(inputStream, interpreterDefs);
				return false;
			} catch (IOException ioe) {
				DLTKLaunchingPlugin.log(ioe);
			}
		}
		return true;
	}

	/**
	 * Performs string substitution on the given expression.
	 *
	 * @param expression
	 * @return expression after string substitution
	 * @throws CoreException
	 *
	 */
	private static String substitute(String expression) throws CoreException {
		return VariablesPlugin.getDefault().getStringVariableManager()
				.performStringSubstitution(expression);
	}

	/**
	 * Returns whether the Interpreter install with the specified id was
	 * contributed via the InterpreterInstalls extension point.
	 *
	 * @param id
	 *            Interpreter id
	 * @return whether the Interpreter install was contributed via extension
	 *         point
	 *
	 */
	public static boolean isContributedInterpreterInstall(String id) {
		getInterpreterInstallTypes(); // ensure Interpreters are initialized
		return fgContributedInterpreters.contains(id);
	}

	/**
	 * Evaluates library locations for a IInterpreterInstall. If no library
	 * locations are set on the install, a default location is evaluated and
	 * checked if it exists.
	 *
	 * @return library locations with paths that exist or are empty
	 *
	 */
	public static LibraryLocation[] getLibraryLocations(
			IInterpreterInstall interperterInstall) {
		return getLibraryLocations(interperterInstall, null);
	}

	public static LibraryLocation[] getLibraryLocations(
			IInterpreterInstall interperterInstall, IProgressMonitor monitor) {

		LibraryLocation[] locations = interperterInstall.getLibraryLocations();
		if (locations != null) {
			return locations;
		}

		LibraryLocation[] defaultLocations = interperterInstall
				.getInterpreterInstallType().getDefaultLibraryLocations(
						interperterInstall.getInstallLocation(),
						interperterInstall.getEnvironmentVariables(), monitor);

		List<LibraryLocation> existingDefaultLocations = new ArrayList<>();
		for (int i = 0; i < defaultLocations.length; ++i) {
			LibraryLocation location = defaultLocations[i];

			IFileHandle file = EnvironmentPathUtils
					.getFile(location.getLibraryPath());
			if (file.exists()) {
				existingDefaultLocations.add(location);
			}
		}

		return existingDefaultLocations
				.toArray(new LibraryLocation[existingDefaultLocations.size()]);
	}

	/**
	 * Creates and returns a buildpath entry describing the default interpreter
	 * container entry.
	 *
	 * @return a new IBuildpathEntry that describes the default interpreter
	 *         container entry
	 *
	 */
	public static IBuildpathEntry getDefaultInterpreterContainerEntry() {
		return DLTKCore.newContainerEntry(newDefaultInterpreterContainerPath());
	}

	/**
	 * Returns a path for the interpreter buildpath container identifying the
	 * default interpreter install.
	 *
	 * @return buildpath container path
	 *
	 */
	public static IPath newDefaultInterpreterContainerPath() {
		return new Path(INTERPRETER_CONTAINER);
	}

	/**
	 * Returns a path for the interpreter buildpath container identifying the
	 * specified Interpreter install by type and name.
	 *
	 * @param Interpreter
	 *            Interpreter install
	 * @return buildpath container path
	 *
	 */
	public static IPath newInterpreterContainerPath(
			IInterpreterInstall interpreter) {
		if (interpreter != null) {
			String name = interpreter.getName();
			String typeId = interpreter.getInterpreterInstallType().getId();
			return newInterpreterContainerPath(typeId, name);
		}
		return null;
	}

	/**
	 * Returns a path for the InterpreterEnvironment buildpath container
	 * identifying the specified Interpreter install by type and name.
	 *
	 * @param typeId
	 *            Interpreter install type identifier
	 * @param name
	 *            Interpreter install name
	 * @return buildpath container path
	 *
	 */
	public static IPath newInterpreterContainerPath(String typeId,
			String name) {
		if (typeId == null || name == null) {
			return null;
		}

		IPath path = newDefaultInterpreterContainerPath();
		path = path.append(typeId);
		path = path.append(name.replaceAll("/", "%2F")); //$NON-NLS-1$ //$NON-NLS-2$
		return path;
	}

	/**
	 * Returns the InterpreterEnvironment referenced by the specified
	 * InterpreterEnvironment buildpath container path or <code>null</code> if
	 * none.
	 *
	 * @param InterpreterEnvironmentContainerPath
	 * @return InterpreterEnvironment referenced by the specified
	 *         InterpreterEnvironment buildpath container path or
	 *         <code>null</code>
	 *
	 */
	public static IInterpreterInstall getInterpreterInstall(String nature,
			String environment, IPath InterpreterEnvironmentContainerPath) {
		try {
			return InterpreterContainerInitializer.resolveInterpreter(nature,
					environment, InterpreterEnvironmentContainerPath);
		} catch (CoreException e) {
			return null;
		}
	}

	/**
	 * Returns the <code>IInterpreterInstall</code> represented by the specified
	 * <code>compositeId</code>.
	 *
	 * <p>
	 * If an interpreter can not be found for the given <code>compositeId</code>
	 * , the default interpreter for the specified <code>natureId</code> will be
	 * returned.
	 *
	 * If no default interpreter has been configured, <code>null</code> will be
	 * returned.
	 * </p>
	 *
	 * @param compositeId
	 *            the composite id that specifies an instance of
	 *            IInterpreterInstall
	 * @param natureId
	 *            nature id
	 *
	 * @return IInterpreterInstall instance or <code>null</code> if one can not
	 *         be found.
	 */
	public static IInterpreterInstall getInterpreterInstall(String compositeId,
			String natureId) {
		IInterpreterInstall install = getInterpreterFromCompositeId(
				compositeId);
		if (install == null) {
			DefaultInterpreterEntry entry = new DefaultInterpreterEntry(
					natureId, LocalEnvironment.ENVIRONMENT_ID);
			install = ScriptRuntime.getDefaultInterpreterInstall(entry);
		}

		return install;
	}

	/**
	 * Returns the identifier of the Interpreter install type referenced by the
	 * given InterpreterEnvironment buildpath container path, or
	 * <code>null</code> if none.
	 *
	 * @param InterpreterEnvironmentContainerPath
	 * @return Interpreter install type identifier or <code>null</code>
	 *
	 */
	public static String getInterpreterInstallTypeId(
			IPath InterpreterEnvironmentContainerPath) {
		return InterpreterContainerInitializer
				.getInterpreterTypeId(InterpreterEnvironmentContainerPath);
	}

	/**
	 * Returns the name of the Interpreter install referenced by the given
	 * InterpreterEnvironment buildpath container path, or <code>null</code> if
	 * none.
	 *
	 * @param InterpreterEnvironmentContainerPath
	 * @return Interpreter name or <code>null</code>
	 *
	 */
	public static String getInterpreterInstallName(
			IPath InterpreterEnvironmentContainerPath) {
		return InterpreterContainerInitializer
				.getInterpreterName(InterpreterEnvironmentContainerPath);
	}

	/**
	 * Returns a runtime buildpath entry identifying the InterpreterEnvironment
	 * to use when launching the specified configuration or <code>null</code> if
	 * none is specified. The entry returned represents a either abuildpath
	 * container that resolves to a interpreter.
	 * <p>
	 * The entry is resolved as follows:
	 * <ol>
	 * <li>If the <code>ATTR_CONTAINER_PATH</code> is present, it is used to
	 * create a buildpath container referring to a interpreter.</li>
	 * <li>When such attribute are not specified, a default entry is created
	 * which refers to the interpreter referenced by the build path of the
	 * configuration's associated script project. This could be a buildpath
	 * variable or buildpath container.</li>
	 * <li>When there is no script project associated with a configuration, the
	 * workspace default interpreter is used to create a container path.</li>
	 * </ol>
	 * </p>
	 *
	 * @param configuration
	 * @return buildpath container path identifying a interpreter or
	 *         <code>null</code>
	 * @exception org.eclipse.core.runtime.CoreException
	 *                if an exception occurs retrieving attributes from the
	 *                specified launch configuration
	 */
	public static IRuntimeBuildpathEntry computeInterpreterEntry(
			ILaunchConfiguration configuration) throws CoreException {
		String containerAttr = configuration.getAttribute(
				ScriptLaunchConfigurationConstants.ATTR_CONTAINER_PATH,
				(String) null);
		IPath containerPath = null;
		if (containerAttr == null) {
			// default interpreter for the launch configuration
			IScriptProject proj = getScriptProject(configuration);
			if (proj == null) {
				containerPath = newDefaultInterpreterContainerPath();
			} else {
				return computeInterpreterEntry(proj);
			}
		} else {
			containerPath = Path.fromPortableString(containerAttr);
		}
		if (containerPath != null) {
			return newRuntimeContainerBuildpathEntry(containerPath,
					IRuntimeBuildpathEntry.STANDARD_ENTRY);
		}
		return null;
	}

	/**
	 * Returns a runtime buildpath entry identifying the InterpreterEnvironment
	 * referenced by the specified project, or <code>null</code> if none. The
	 * entry returned represents a either a buildpath variable or buildpath
	 * container that resolves to a InterpreterEnvironment.
	 *
	 * @param project
	 *            Script project
	 * @return InterpreterEnvironment runtime buildpath entry or
	 *         <code>null</code>
	 * @exception org.eclipse.core.runtime.CoreException
	 *                if an exception occurs accessing the project's buildpath
	 *
	 */
	public static IRuntimeBuildpathEntry computeInterpreterEntry(
			IScriptProject project) throws CoreException {
		IBuildpathEntry[] rawBuildpath = project.getRawBuildpath();
		IRuntimeBuildpathEntryResolver2 resolver = null;
		for (int i = 0; i < rawBuildpath.length; i++) {
			IBuildpathEntry entry = rawBuildpath[i];
			switch (entry.getEntryKind()) {
			case IBuildpathEntry.BPE_CONTAINER:
				resolver = getContainerResolver(entry.getPath().segment(0));
				if (resolver != null) {
					if (resolver.isInterpreterInstallReference(
							getNatureFromProject(project),
							getEnvironmentFromProject(project), entry)) {
						IBuildpathContainer container = DLTKCore
								.getBuildpathContainer(entry.getPath(),
										project);
						if (container != null) {
							switch (container.getKind()) {
							case IBuildpathContainer.K_APPLICATION:
								break;
							case IBuildpathContainer.K_DEFAULT_SYSTEM:
								return newRuntimeContainerBuildpathEntry(
										entry.getPath(),
										IRuntimeBuildpathEntry.STANDARD_ENTRY);
							case IBuildpathContainer.K_SYSTEM:
								return newRuntimeContainerBuildpathEntry(
										entry.getPath(),
										IRuntimeBuildpathEntry.BOOTSTRAP_ENTRY);
							}
						}
					}
				}
				break;
			}

		}
		return null;
	}

	/**
	 * Returns whether the given runtime buildpath entry refers to a Interpreter
	 * install.
	 *
	 * @param entry
	 * @return whether the given runtime buildpath entry refers to a Interpreter
	 *         install
	 *
	 */
	public static boolean isInterpreterInstallReference(String lang,
			String environment, IRuntimeBuildpathEntry entry) {
		IBuildpathEntry buildpathEntry = entry.getBuildpathEntry();
		if (buildpathEntry != null) {
			switch (buildpathEntry.getEntryKind()) {
			case IBuildpathEntry.BPE_CONTAINER:
				IRuntimeBuildpathEntryResolver2 resolver = getContainerResolver(
						buildpathEntry.getPath().segment(0));
				if (resolver != null) {
					return resolver.isInterpreterInstallReference(lang,
							environment, buildpathEntry);
				}
				break;
			}
		}
		return false;
	}

	/**
	 * Adds the given listener to the list of registered Interpreter install
	 * changed listeners. Has no effect if an identical listener is already
	 * registered.
	 *
	 * @param listener
	 *            the listener to add
	 *
	 */
	public static void addInterpreterInstallChangedListener(
			IInterpreterInstallChangedListener listener) {
		fgInterpreterListeners.add(listener);
	}

	/**
	 * Removes the given listener from the list of registered Interpreter
	 * install changed listeners. Has no effect if an identical listener is not
	 * already registered.
	 *
	 * @param listener
	 *            the listener to remove
	 *
	 */
	public static void removeInterpreterInstallChangedListener(
			IInterpreterInstallChangedListener listener) {
		fgInterpreterListeners.remove(listener);
	}

	private static void notifyDefaultInterpreterChanged(
			IInterpreterInstall previous, IInterpreterInstall current) {
		for (IInterpreterInstallChangedListener listener : fgInterpreterListeners) {
			listener.defaultInterpreterInstallChanged(previous, current);
		}
	}

	/**
	 * Notifies all Interpreter install changed listeners of the given property
	 * change.
	 *
	 * @param event
	 *            event describing the change.
	 *
	 */
	public static void fireInterpreterChanged(PropertyChangeEvent event) {
		for (IInterpreterInstallChangedListener listener : fgInterpreterListeners) {
			listener.interpreterChanged(event);
		}
	}

	/**
	 * Notifies all Interpreter install changed listeners of the Interpreter
	 * addition
	 *
	 * @param Interpreter
	 *            the Interpreter that has been added
	 *
	 */
	public static void fireInterpreterAdded(IInterpreterInstall Interpreter) {
		if (!fgInitializingInterpreters) {
			for (IInterpreterInstallChangedListener listener : fgInterpreterListeners) {
				listener.interpreterAdded(Interpreter);
			}
		}
	}

	/**
	 * Notifies all Interpreter install changed listeners of the Interpreter
	 * removal
	 *
	 * @param Interpreter
	 *            the Interpreter that has been removed
	 *
	 */
	public static void fireInterpreterRemoved(IInterpreterInstall Interpreter) {
		for (IInterpreterInstallChangedListener listener : fgInterpreterListeners) {
			listener.interpreterRemoved(Interpreter);
		}
	}

	/**
	 * Returns the preference store for the launching plug-in.
	 *
	 * @return the preference store for the launching plug-in
	 * @since 5.0 return type changed to {@link IEclipsePreferences}
	 */
	public static IEclipsePreferences getPreferences() {
		return InstanceScope.INSTANCE.getNode(DLTKLaunchingPlugin.PLUGIN_ID);
	}

	/**
	 * Saves the preferences for the launching plug-in.
	 *
	 *
	 */
	public static void savePreferences() {
		try {
			getPreferences().flush();
		} catch (BackingStoreException e) {
			DLTKLaunchingPlugin.log(e);
		}
	}

	/**
	 * Registers the given resolver for the specified container.
	 *
	 * @param resolver
	 *            runtime buildpath entry resolver
	 * @param containerIdentifier
	 *            identifier of the buildpath container to register for
	 *
	 */
	public static void addContainerResolver(
			IRuntimeBuildpathEntryResolver resolver,
			String containerIdentifier) {
		Map<String, IRuntimeBuildpathEntryResolver> map = getContainerResolvers();
		map.put(containerIdentifier, resolver);
	}

	/**
	 * Returns all registered container resolvers.
	 */
	private static Map<String, IRuntimeBuildpathEntryResolver> getContainerResolvers() {
		if (fgContainerResolvers == null) {
			initializeResolvers();
		}
		return fgContainerResolvers;
	}

	private static void initializeResolvers() {
		IExtensionPoint point = Platform.getExtensionRegistry()
				.getExtensionPoint(DLTKLaunchingPlugin.PLUGIN_ID,
						EXTENSION_POINT_RUNTIME_BUILDPATH_ENTRY_RESOLVERS);
		IConfigurationElement[] extensions = point.getConfigurationElements();
		fgContainerResolvers = new HashMap<>(extensions.length);
		fgRuntimeBuildpathEntryResolvers = new HashMap<>(extensions.length);
		for (int i = 0; i < extensions.length; i++) {
			RuntimeBuildpathEntryResolver res = new RuntimeBuildpathEntryResolver(
					extensions[i]);
			String container = res.getContainerId();
			String entryId = res.getRuntimeBuildpathEntryId();
			if (container != null) {
				fgContainerResolvers.put(container, res);
			}
			if (entryId != null) {
				fgRuntimeBuildpathEntryResolvers.put(entryId, res);
			}
		}
	}

	/**
	 * Returns all registered buildpath providers.
	 */
	private static Map<String, IRuntimeBuildpathProvider> getBuildpathProviders() {
		if (fgPathProviders == null) {
			initializeProviders();
		}
		return fgPathProviders;
	}

	private static void initializeProviders() {
		IExtensionPoint point = Platform.getExtensionRegistry()
				.getExtensionPoint(DLTKLaunchingPlugin.PLUGIN_ID,
						EXTENSION_POINT_RUNTIME_BUILDPATH_PROVIDERS);
		IConfigurationElement[] extensions = point.getConfigurationElements();
		fgPathProviders = new HashMap<>(extensions.length);
		for (int i = 0; i < extensions.length; i++) {
			RuntimeBuildpathProvider res = new RuntimeBuildpathProvider(
					extensions[i]);
			fgPathProviders.put(res.getIdentifier(), res);
		}
	}

	/**
	 * Returns the resolver registered for the given container id, or
	 * <code>null</code> if none.
	 *
	 * @param containerId
	 *            the container to determine the resolver for
	 * @return the resolver registered for the given container id, or
	 *         <code>null</code> if none
	 */
	private static IRuntimeBuildpathEntryResolver2 getContainerResolver(
			String containerId) {
		return (IRuntimeBuildpathEntryResolver2) getContainerResolvers()
				.get(containerId);
	}

	/**
	 * Returns a collection of paths that should be appended to the given
	 * project's library path when launched. Entries are searched for on the
	 * project's build path as extra buildpath attributes. Each entry represents
	 * an absolute path in the local file system.
	 *
	 * @param project
	 *            the project to compute the <code>java.library.path</code> for
	 * @param requiredProjects
	 *            whether to consider entries in required projects
	 * @return a collection of paths representing entries that should be
	 *         appended to the given project's <code>java.library.path</code>
	 * @throws CoreException
	 *             if unable to compute the Script library path
	 *
	 * @see org.eclipse.dltk.core.IBuildpathAttribute
	 * @see ScriptRuntime#BUILDPATH_ATTR_LIBRARY_PATH_ENTRY
	 */
	public static String[] computeScriptLibraryPath(IScriptProject project,
			boolean requiredProjects) throws CoreException {
		Set<IScriptProject> visited = new HashSet<>();
		List<String> entries = new ArrayList<>();
		gatherScriptLibraryPathEntries(project, requiredProjects, visited,
				entries);
		List<String> resolved = new ArrayList<>(entries.size());
		IStringVariableManager manager = VariablesPlugin.getDefault()
				.getStringVariableManager();
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		for (String entry : entries) {
			String resolvedEntry = manager.performStringSubstitution(entry);
			IPath path = new Path(resolvedEntry);
			if (path.isAbsolute()) {
				File file = path.toFile();
				resolved.add(file.getAbsolutePath());
			} else {
				IResource resource = root.findMember(path);
				if (resource != null) {
					IPath location = resource.getLocation();
					if (location != null) {
						resolved.add(location.toFile().getAbsolutePath());
					}
				}
			}
		}
		return resolved.toArray(new String[resolved.size()]);
	}

	/**
	 * Gathers all Script library entries for the given project and optionally
	 * its required projects.
	 *
	 * @param project
	 *            project to gather entries for
	 * @param requiredProjects
	 *            whether to consider required projects
	 * @param visited
	 *            projects already considered
	 * @param entries
	 *            collection to add library entries to
	 * @throws CoreException
	 *             if unable to gather buildpath entries
	 *
	 */
	private static void gatherScriptLibraryPathEntries(IScriptProject project,
			boolean requiredProjects, Set<IScriptProject> visited,
			List<String> entries) throws CoreException {
		if (visited.contains(project)) {
			return;
		}
		visited.add(project);
		IBuildpathEntry[] rawBuildpath = project.getRawBuildpath();
		IBuildpathEntry[] required = processScriptLibraryPathEntries(project,
				requiredProjects, rawBuildpath, entries);
		if (required != null) {
			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
			for (int i = 0; i < required.length; i++) {
				IBuildpathEntry entry = required[i];
				String projectName = entry.getPath().segment(0);
				IProject p = root.getProject(projectName);
				if (p.exists()) {
					IScriptProject requiredProject = DLTKCore.create(p);
					if (requiredProject != null) {
						gatherScriptLibraryPathEntries(requiredProject,
								requiredProjects, visited, entries);
					}
				}
			}
		}
	}

	/**
	 * Adds all library path extra buildpath entry values to the given entries
	 * collection specified on the given project's buildpath, and returns a
	 * collection of required projects, or <code>null</code>.
	 *
	 * @param project
	 *            project being processed
	 * @param collectRequired
	 *            whether to collect required projects
	 * @param buildpathEntries
	 *            the project's raw buildpath
	 * @param entries
	 *            collection to add script library path entries to
	 * @return required project buildpath entries or <code>null</code>
	 * @throws CoreException
	 *
	 */
	private static IBuildpathEntry[] processScriptLibraryPathEntries(
			IScriptProject project, boolean collectRequired,
			IBuildpathEntry[] buildpathEntries, List<String> entries)
			throws CoreException {
		List<IBuildpathEntry> req = null;
		for (int i = 0; i < buildpathEntries.length; i++) {
			IBuildpathEntry entry = buildpathEntries[i];
			IBuildpathAttribute[] extraAttributes = entry.getExtraAttributes();
			for (int j = 0; j < extraAttributes.length; j++) {
				String[] paths = getLibraryPaths(extraAttributes[j]);
				if (paths != null) {
					for (int k = 0; k < paths.length; k++) {
						entries.add(paths[k]);
					}
				}
			}
			if (entry.getEntryKind() == IBuildpathEntry.BPE_CONTAINER) {
				IBuildpathContainer container = DLTKCore
						.getBuildpathContainer(entry.getPath(), project);
				if (container != null) {
					IBuildpathEntry[] requiredProjects = processScriptLibraryPathEntries(
							project, collectRequired,
							container.getBuildpathEntries(), entries);
					if (requiredProjects != null) {
						if (req == null) {
							req = new ArrayList<>();
						}
						for (int j = 0; j < requiredProjects.length; j++) {
							req.add(requiredProjects[j]);
						}
					}
				}
			} else if (collectRequired
					&& entry.getEntryKind() == IBuildpathEntry.BPE_PROJECT) {
				if (req == null) {
					req = new ArrayList<>();
				}
				req.add(entry);
			}
		}
		if (req != null) {
			return req.toArray(new IBuildpathEntry[req.size()]);
		}
		return null;
	}

	/**
	 * Creates a new buildpath attribute referencing a list of shared libraries
	 * that should appear on the <code>-Djava.library.path</code> system
	 * property at runtime for an associated {@link IBuildpathEntry}.
	 * <p>
	 * The factory methods <code>newLibraryPathsAttribute(String[])</code> and
	 * <code>getLibraryPaths(IBuildpathAttribute)</code> should be used to
	 * encode and decode the attribute value.
	 * </p>
	 *
	 * @param paths
	 *            an array of strings representing paths of shared libraries.
	 *            Each string is used to create an <code>IPath</code> using the
	 *            constructor <code>Path(String)</code>, and may contain
	 *            <code>IStringVariable</code>'s. Variable substitution is
	 *            performed on each string before a path is constructed from a
	 *            string.
	 * @return a buildpath attribute with the name
	 *         <code>CLASSPATH_ATTR_LIBRARY_PATH_ENTRY</code> and an value
	 *         encoded to the specified paths.
	 *
	 */
	public static IBuildpathAttribute newLibraryPathsAttribute(String[] paths) {
		StringBuffer value = new StringBuffer();
		for (int i = 0; i < paths.length; i++) {
			value.append(paths[i]);
			if (i < (paths.length - 1)) {
				value.append("|"); //$NON-NLS-1$
			}
		}
		return DLTKCore.newBuildpathAttribute(BUILDPATH_ATTR_LIBRARY_PATH_ENTRY,
				value.toString());
	}

	/**
	 * Returns an array of strings referencing shared libraries that should
	 * appear on the <code>-Djava.library.path</code> system property at runtime
	 * for an associated {@link IBuildpathEntry}, or <code>null</code> if the
	 * given attribute is not a <code>CLASSPATH_ATTR_LIBRARY_PATH_ENTRY</code>.
	 * Each string is used to create an <code>IPath</code> using the constructor
	 * <code>Path(String)</code>, and may contain <code>IStringVariable</code>
	 * 's.
	 * <p>
	 * The factory methods <code>newLibraryPathsAttribute(String[])</code> and
	 * <code>getLibraryPaths(IBuildpathAttribute)</code> should be used to
	 * encode and decode the attribute value.
	 * </p>
	 *
	 * @param attribute
	 *            a <code>CLASSPATH_ATTR_LIBRARY_PATH_ENTRY</code> buildpath
	 *            attribute
	 * @return an array of strings referencing shared libraries that should
	 *         appear on the <code>-Djava.library.path</code> system property at
	 *         runtime for an associated {@link IBuildpathEntry}, or
	 *         <code>null</code> if the given attribute is not a
	 *         <code>CLASSPATH_ATTR_LIBRARY_PATH_ENTRY</code>. Each string is
	 *         used to create an <code>IPath</code> using the constructor
	 *         <code>Path(String)</code>, and may contain
	 *         <code>IStringVariable</code>'s.
	 *
	 */
	public static String[] getLibraryPaths(IBuildpathAttribute attribute) {
		if (BUILDPATH_ATTR_LIBRARY_PATH_ENTRY.equals(attribute.getName())) {
			String value = attribute.getValue();
			return value.split("\\|"); //$NON-NLS-1$
		}
		return null;
	}

	/**
	 * Loads contributed interpreter installs
	 *
	 */
	private static void addInterpreterExtensions(
			InterpreterDefinitionsContainer InterpreterDefs) {
		IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
				.getExtensionPoint(DLTKLaunchingPlugin.PLUGIN_ID,
						ScriptRuntime.EXTENSION_POINT_INTERPRETER_INSTALLS);
		IConfigurationElement[] configs = extensionPoint
				.getConfigurationElements();
		for (int i = 0; i < configs.length; i++) {
			IConfigurationElement element = configs[i];
			try {
				if ("interpreterInstall".equals(element.getName())) { //$NON-NLS-1$
					String InterpreterType = element
							.getAttribute("interpreterInstallType"); //$NON-NLS-1$
					if (InterpreterType == null) {
						abort(MessageFormat.format(
								"Missing required interpreterInstallType attribute for interpreterInstall contributed by {0}", //$NON-NLS-1$
								element.getContributor().getName()), null);
					}
					String id = element.getAttribute("id"); //$NON-NLS-1$
					if (id == null) {
						abort(MessageFormat.format(
								"Missing required id attribute for interpreterInstall contributed by {0}", //$NON-NLS-1$
								element.getContributor().getName()), null);
					}
					IInterpreterInstallType installType = getInterpreterInstallType(
							InterpreterType);
					if (installType == null) {
						throw abort(MessageFormat.format(
								"InterpreterInstall {0} contributed by {1} references undefined Interpreter install type {2}", //$NON-NLS-1$
								id, element.getContributor().getName(),
								InterpreterType), null);
					}
					IInterpreterInstall install = installType
							.findInterpreterInstall(id);
					if (install == null) {
						// only load/create if first time we've seen this
						// Interpreter install
						String name = element.getAttribute("name"); //$NON-NLS-1$
						if (name == null) {
							abort(MessageFormat.format(
									"interpreterInstall {0} contributed by {1} missing required attribute name", //$NON-NLS-1$
									id, element.getContributor().getName()),
									null);
						}
						final String home = element.getAttribute("home"); //$NON-NLS-1$
						if (home == null) {
							abort(MessageFormat.format(
									"interpreterInstall {0} contributed by {1} missing required attribute home", //$NON-NLS-1$
									id, element.getContributor().getName()),
									null);
						}
						String InterpreterArgs = element
								.getAttribute("interpreterArgs"); //$NON-NLS-1$
						InterpreterStandin standin = new InterpreterStandin(
								installType, id);
						standin.setName(name);

						// Only local installs can be contributed, so
						// use local environment
						final IEnvironment localEnv = EnvironmentManager
								.getLocalEnvironment();

						IFileHandle homeFile = localEnv
								.getFile(toPath(element, substitute(home)));
						if (homeFile.exists()) {
							// adjust for relative path names
							homeFile = localEnv.getFile(
									new Path(homeFile.getCanonicalPath()));
						}
						IStatus status = installType.validateInstallLocation(
								homeFile, standin.getEnvironmentVariables(),
								standin.getLibraryLocations(),
								new NullProgressMonitor());
						if (!status.isOK()) {
							abort(MessageFormat.format(
									"Illegal install location {0} for interpreterInstall {1} contributed by {2}: {3}", //$NON-NLS-1$
									home, id,
									element.getContributor().getName(),
									status.getMessage()), null);
						}
						standin.setInstallLocation(homeFile);

						if (InterpreterArgs != null) {
							standin.setInterpreterArgs(InterpreterArgs);
						}
						IConfigurationElement[] libraries = element
								.getChildren("library"); //$NON-NLS-1$
						LibraryLocation[] locations = null;
						if (libraries.length > 0) {
							locations = new LibraryLocation[libraries.length];
							for (int j = 0; j < libraries.length; j++) {
								IConfigurationElement library = libraries[j];
								String libPathStr = library
										.getAttribute("path"); //$NON-NLS-1$
								if (libPathStr == null) {
									abort(MessageFormat.format(
											"library for interpreterInstall {0} contributed by {1} missing required attribute libPath", //$NON-NLS-1$
											id,
											element.getContributor().getName()),
											null);
								}

								locations[j] = new LibraryLocation(
										homeFile.getFullPath().append(
												substitute(libPathStr)));
							}
						}
						standin.setLibraryLocations(locations);
						InterpreterDefs.addInterpreter(standin, true);
					}
					fgContributedInterpreters.add(id);
				} else {
					abort(MessageFormat.format(
							"Illegal element {0} in InterpreterInstalls extension contributed by {1}", //$NON-NLS-1$
							element.getName(),
							element.getContributor().getName()), null);
				}
			} catch (CoreException e) {
				DLTKLaunchingPlugin.log(e);
			}
		}
	}

	private static IPath toPath(IConfigurationElement element, String path)
			throws CoreException {
		String bundleId = element.getAttribute("bundle");
		if (bundleId != null) {
			if (bundleId.equals(".")) {
				bundleId = element.getContributor().getName();
			}
			final Bundle bundle = Platform.getBundle(bundleId);
			if (bundle != null) {
				try {
					final File bundleFile = FileLocator.getBundleFile(bundle);
					final IPath bundlePath = new Path(
							bundleFile.getCanonicalPath());
					return bundlePath.append(new Path(path));
				} catch (IOException e) {
					abort(NLS.bind("Error resolving {0} bundle location",
							bundleId), e);
				}
			}
		}
		return new Path(path);
	}

	private static InterpreterStandin[] detectInterpreterInstall(
			String natureId, List<IInterpreterInstallType> interpTypes) {
		// Try to create a interpreter install using the install location
		for (IInterpreterInstallType interpType : interpTypes) {
			final IFileHandle[] detectedLocations = interpType
					.detectInstallLocations();
			if (detectedLocations != null && detectedLocations.length != 0) {
				// Make sure the interpreter id is unique
				long unique = System.currentTimeMillis();
				final InterpreterStandin[] result = new InterpreterStandin[detectedLocations.length];
				for (int j = 0; j < detectedLocations.length; ++j) {
					while (interpType.findInterpreterInstall(
							String.valueOf(unique)) != null) {
						unique++;
					}
					final IFileHandle location = detectedLocations[j];
					// Create a standin for the detected interpreter
					final InterpreterStandin detected = new InterpreterStandin(
							interpType, String.valueOf(unique++));
					detected.setInstallLocation(location);
					detected.setName(interpType
							.generateDetectedInterpreterName(location));
					result[j] = detected;
				}
				return result;
			}
		}
		return null;
	}

	private static Map<String, List<IInterpreterInstallType>> getInterpreterTypesByNature() {
		Map<String, List<IInterpreterInstallType>> result = new HashMap<>();
		for (IInterpreterInstallType type : fgInterpreterTypes) {
			String natureId = type.getNatureId();
			if (!result.containsKey(natureId)) {
				result.put(natureId, new ArrayList<IInterpreterInstallType>());
			}
			result.get(natureId).add(type);
		}
		return result;
	}

	private static Map<String, List<IInterpreterInstall>> getValidInterpretersByNature(
			List<IInterpreterInstall> validInterpreters) {
		Map<String, List<IInterpreterInstall>> result = new HashMap<>();
		for (IInterpreterInstall install : validInterpreters) {
			String natureId = install.getNatureId();
			if (!result.containsKey(natureId)) {
				result.put(natureId, new ArrayList<IInterpreterInstall>());
			}
			result.get(natureId).add(install);
		}
		return result;
	}

	/**
	 * Perform Interpreter type and Interpreter install initialization. Does not
	 * hold locks while performing change notification.
	 *
	 *
	 */
	private static void initializeInterpreters() {
		InterpreterDefinitionsContainer defs = null;
		boolean setPref = false;
		synchronized (fgInterpreterLock) {
			if (fgInterpreterTypes == null) {
				try {
					fgInitializingInterpreters = true;
					// 1. load Interpreter type extensions
					initializeInterpreterTypeExtensions();
					defs = new InterpreterDefinitionsContainer();

					// 2. add persisted Interpreters
					setPref = addPersistedInterpreters(defs);

					// 3. if there are none, detect interpreters
					Map<String, List<IInterpreterInstallType>> typesByNature = getInterpreterTypesByNature();
					Map<String, List<IInterpreterInstall>> interpsByNature = getValidInterpretersByNature(
							defs.getValidInterpreterList());
					for (String natureId : typesByNature.keySet()) {
						if (!interpsByNature.containsKey(natureId)
								|| interpsByNature.get(natureId).isEmpty()) {
							// calling out to detectInterpreterInstall(nature)
							// could allow clients to change
							// Interpreter settings (i.e. call back into change
							// Interpreter settings).
							InterpreterListener listener = new InterpreterListener();
							addInterpreterInstallChangedListener(listener);
							setPref = true;
							InterpreterStandin[] interp = detectInterpreterInstall(
									natureId, typesByNature.get(natureId));
							removeInterpreterInstallChangedListener(listener);
							if (!listener.isChanged()) {
								if (interp != null) {
									for (InterpreterStandin standin : interp) {
										defs.addInterpreter(standin);
									}
									defs.setDefaultInterpreterInstallCompositeID(
											new DefaultInterpreterEntry(
													natureId,
													interp[0]
															.getEnvironmentId()),
											getCompositeIdFromInterpreter(
													interp[0]));
								}
							} else {
								// interpreters were changed - reflect current
								// settings
								addPersistedInterpreters(defs);
								// copy default interpreters
								for (Map.Entry<DefaultInterpreterEntry, String> entry : fgDefaultInterpreterId
										.entrySet()) {
									defs.setDefaultInterpreterInstallCompositeID(
											entry.getKey(), entry.getValue());
								}
							}
						}
					}

					// 4. load contributed Interpreter installs
					addInterpreterExtensions(defs);

					// 5. verify default interpreters is valid
					DefaultInterpreterEntry[] natures = defs
							.getInterpreterNatures();
					for (int i = 0; i < natures.length; i++) {
						String defId = defs
								.getDefaultInterpreterInstallCompositeID(
										natures[i]);
						boolean validDef = false;
						if (defId != null) {
							for (IInterpreterInstall iterpreter : defs
									.getValidInterpreterList()) {
								if (getCompositeIdFromInterpreter(iterpreter)
										.equals(defId)) {
									validDef = true;
									break;
								}
							}
						}

						if (!validDef) {
							// use the first as the default
							setPref = true;
							List<IInterpreterInstall> list = defs
									.getValidInterpreterList(natures[i]);
							if (!list.isEmpty()) {
								IInterpreterInstall Interpreter = list.get(0);
								defs.setDefaultInterpreterInstallCompositeID(
										natures[i],
										getCompositeIdFromInterpreter(
												Interpreter));
							}
						}

						String defInstCID = defs
								.getDefaultInterpreterInstallCompositeID(
										natures[i]);
						fgDefaultInterpreterId.put(natures[i], defInstCID);
						String defIntCTypeID = defs
								.getDefaultInterpreterInstallConnectorTypeID(
										natures[i]);
						fgDefaultInterpreterConnectorId.put(natures[i],
								defIntCTypeID);
					}
					// Create the underlying interpreters for each valid
					// Interpreter
					List<IInterpreterInstall> InterpreterList = defs
							.getValidInterpreterList();
					Iterator<IInterpreterInstall> InterpreterListIterator = InterpreterList
							.iterator();
					while (InterpreterListIterator.hasNext()) {
						InterpreterStandin InterpreterStandin = (InterpreterStandin) InterpreterListIterator
								.next();
						InterpreterStandin.convertToRealInterpreter();
					}

				} finally {
					fgInitializingInterpreters = false;
				}
			}
		}
		if (defs != null) {
			// notify of initial Interpreters for backwards compatibility
			IInterpreterInstallType[] installTypes = getInterpreterInstallTypes();
			for (int i = 0; i < installTypes.length; i++) {
				IInterpreterInstallType type = installTypes[i];
				IInterpreterInstall[] installs = type.getInterpreterInstalls();
				if (installs != null) {
					for (int j = 0; j < installs.length; j++) {
						fireInterpreterAdded(installs[j]);
					}
				}
			}

			// save settings if required
			if (setPref) {
				try {
					String xml = defs.getAsXML();
					getPreferences().put(PREF_INTERPRETER_XML, xml);
				} catch (ParserConfigurationException e) {
					DLTKLaunchingPlugin.log(e);
				} catch (IOException e) {
					DLTKLaunchingPlugin.log(e);
				} catch (TransformerException e) {
					DLTKLaunchingPlugin.log(e);
				}

			}

		}
	}

	/**
	 * Returns a new runtime buildpath entry containing the default buildpath
	 * for the specified script project.
	 *
	 * @param project
	 *            project
	 * @return runtime buildpath entry
	 *
	 */
	public static IRuntimeBuildpathEntry newDefaultProjectBuildpathEntry(
			IScriptProject project) {
		return new DefaultProjectBuildpathEntry(project);
	}

	/**
	 * Returns a new runtime buildpath entry for the given project.
	 *
	 * @param project
	 *            Script project
	 * @return runtime buildpath entry
	 *
	 */
	public static IRuntimeBuildpathEntry newProjectRuntimeBuildpathEntry(
			IScriptProject project) {
		IBuildpathEntry cpe = DLTKCore
				.newProjectEntry(project.getProject().getFullPath());
		return newRuntimeBuildpathEntry(cpe);
	}

	/**
	 * Returns a new runtime buildpath entry for the given archive.
	 *
	 * @param resource
	 *            archive resource
	 * @return runtime buildpath entry
	 *
	 */
	public static IRuntimeBuildpathEntry newArchiveRuntimeBuildpathEntry(
			IResource resource) {
		IBuildpathEntry cpe = DLTKCore.newLibraryEntry(resource.getFullPath());
		return newRuntimeBuildpathEntry(cpe);
	}

	/**
	 * Returns a new runtime buildpath entry for the given archive (possibly
	 * external).
	 *
	 * @param path
	 *            absolute path to an archive
	 * @return runtime buildpath entry
	 *
	 */
	public static IRuntimeBuildpathEntry newArchiveRuntimeBuildpathEntry(
			IPath path) {
		IBuildpathEntry cpe = DLTKCore.newLibraryEntry(path);
		return newRuntimeBuildpathEntry(cpe);
	}

	/**
	 * Returns a runtime buildpath entry for the given container path with the
	 * given buildpath property.
	 *
	 * @param path
	 *            container path
	 * @param buildpathProperty
	 *            the type of entry - one of <code>USER_CLASSES</code>, or
	 *            <code>STANDARD_CLASSES</code>
	 * @return runtime buildpath entry
	 * @exception CoreException
	 *                if unable to construct a runtime buildpath entry
	 *
	 */
	public static IRuntimeBuildpathEntry newRuntimeContainerBuildpathEntry(
			IPath path, int buildpathProperty) throws CoreException {
		return newRuntimeContainerBuildpathEntry(path, buildpathProperty, null);
	}

	/**
	 * Returns a runtime buildpath entry for the given container path with the
	 * given buildpath property to be resolved in the context of the given
	 * Script project.
	 *
	 * @param path
	 *            container path
	 * @param buildpathProperty
	 *            the type of entry - one of <code>USER_CLASSES</code>, or
	 *            <code>STANDARD_CLASSES</code>
	 * @param project
	 *            Script project context used for resolution, or
	 *            <code>null</code> if to be resolved in the context of the
	 *            launch configuration this entry is referenced in
	 * @return runtime buildpath entry
	 * @exception CoreException
	 *                if unable to construct a runtime buildpath entry
	 */
	public static IRuntimeBuildpathEntry newRuntimeContainerBuildpathEntry(
			IPath path, int buildpathProperty, IScriptProject project)
			throws CoreException {
		IBuildpathEntry cpe = DLTKCore.newContainerEntry(path);
		RuntimeBuildpathEntry entry = new RuntimeBuildpathEntry(cpe,
				buildpathProperty);
		entry.setScriptProject(project);
		return entry;
	}

	/**
	 * Returns a runtime buildpath entry constructed from the given memento.
	 *
	 * @param memento
	 *            a memento for a runtime buildpath entry
	 * @return runtime buildpath entry
	 * @exception CoreException
	 *                if unable to construct a runtime buildpath entry
	 */
	public static IRuntimeBuildpathEntry newRuntimeBuildpathEntry(
			String memento) throws CoreException {
		try {
			Element root = null;
			DocumentBuilder parser = DLTKLaunchingPlugin.getParser();
			StringReader reader = new StringReader(memento);
			InputSource source = new InputSource(reader);
			root = parser.parse(source).getDocumentElement();

			String id = root.getAttribute("id"); //$NON-NLS-1$
			if (id == null || id.length() == 0) {
				// assume an old format
				return new RuntimeBuildpathEntry(root);
			}
			// get the extension & create a new one
			IRuntimeBuildpathEntry2 entry = DLTKLaunchingPlugin.getDefault()
					.newRuntimeBuildpathEntry(id);
			NodeList list = root.getChildNodes();
			for (int i = 0; i < list.getLength(); i++) {
				Node node = list.item(i);
				if (node.getNodeType() == Node.ELEMENT_NODE) {
					Element element = (Element) node;
					if ("memento".equals(element.getNodeName())) { //$NON-NLS-1$
						entry.initializeFrom(element);
					}
				}
			}
			return entry;
		} catch (SAXException e) {
			abort(LaunchingMessages.ScriptRuntime_31, e);
		} catch (IOException e) {
			abort(LaunchingMessages.ScriptRuntime_32, e);
		}
		return null;
	}

	/**
	 * Returns a runtime buildpath entry that corresponds to the given buildpath
	 * entry. The buildpath entry may not be of type <code>CPE_SOURCE</code> or
	 * <code>BPE_CONTAINER</code>.
	 *
	 * @param entry
	 *            a buildpath entry
	 * @return runtime buildpath entry
	 */
	private static IRuntimeBuildpathEntry newRuntimeBuildpathEntry(
			IBuildpathEntry entry) {
		return new RuntimeBuildpathEntry(entry);
	}

	/**
	 * Computes and returns the default unresolved runtime buildpath for the
	 * given project.
	 *
	 * @return runtime buildpath entries
	 * @exception CoreException
	 *                if unable to compute the runtime buildpath
	 * @see IRuntimeBuildpathEntry
	 *
	 */
	public static IRuntimeBuildpathEntry[] computeUnresolvedRuntimeBuildpath(
			IScriptProject project) throws CoreException {
		IBuildpathEntry[] entries = project.getRawBuildpath();
		List<IRuntimeBuildpathEntry> buildpathEntries = new ArrayList<>(3);
		for (int i = 0; i < entries.length; i++) {
			IBuildpathEntry entry = entries[i];
			switch (entry.getEntryKind()) {
			case IBuildpathEntry.BPE_CONTAINER:
				IBuildpathContainer container = DLTKCore
						.getBuildpathContainer(entry.getPath(), project);
				if (container != null) {
					switch (container.getKind()) {
					case IBuildpathContainer.K_APPLICATION:
						// don't look at application entries
						break;
					case IBuildpathContainer.K_DEFAULT_SYSTEM:
					case IBuildpathContainer.K_SYSTEM:
						buildpathEntries.add(newRuntimeContainerBuildpathEntry(
								container.getPath(),
								IRuntimeBuildpathEntry.STANDARD_ENTRY,
								project));
						break;
					}
				}
				break;
			default:
				break;
			}
		}
		buildpathEntries.add(newDefaultProjectBuildpathEntry(project));
		return buildpathEntries
				.toArray(new IRuntimeBuildpathEntry[buildpathEntries.size()]);
	}

	/**
	 * Returns the buildpath provider for the given launch configuration.
	 *
	 * @param configuration
	 *            launch configuration
	 * @return buildpath provider
	 * @exception CoreException
	 *                if unable to resolve the path provider
	 */
	public static IRuntimeBuildpathProvider getBuildpathProvider(
			ILaunchConfiguration configuration) throws CoreException {
		String providerId = configuration.getAttribute(
				ScriptLaunchConfigurationConstants.ATTR_BUILDPATH_PROVIDER,
				(String) null);
		IRuntimeBuildpathProvider provider = null;
		if (providerId == null) {
			provider = fgDefaultBuildpathProvider;
		} else {
			provider = getBuildpathProviders().get(providerId);
			if (provider == null) {
				abort(MessageFormat.format(LaunchingMessages.ScriptRuntime_26,
						providerId), null);
			}
		}
		return provider;
	}

	public static IRuntimeBuildpathProvider getScriptpathProvider(
			ILaunchConfiguration configuration) throws CoreException {

		String providerId = configuration.getAttribute(
				ScriptLaunchConfigurationConstants.ATTR_SOURCEPATH_PROVIDER,
				(String) null);
		IRuntimeBuildpathProvider provider = null;
		if (providerId == null) {
			provider = fgDefaultSourcepathProvider;
		} else {
			provider = getBuildpathProviders().get(providerId);
			if (provider == null) {
				abort(MessageFormat.format(LaunchingMessages.ScriptRuntime_27,
						providerId), null);
			}
		}
		return provider;
	}

	/**
	 * Performs default resolution for a container entry. Delegates to the
	 * Script model.
	 */
	private static IRuntimeBuildpathEntry[] computeDefaultContainerEntries(
			IRuntimeBuildpathEntry entry, ILaunchConfiguration config)
			throws CoreException {
		IScriptProject project = entry.getScriptProject();

		if (project == null) {
			project = getScriptProject(config);
		}
		return computeDefaultContainerEntries(entry, project);
	}

	/**
	 * Performs default resolution for a container entry. Delegates to the
	 * Script model.
	 */
	private static IRuntimeBuildpathEntry[] computeDefaultContainerEntries(
			IRuntimeBuildpathEntry entry, IScriptProject project)
			throws CoreException {
		if (project == null || entry == null) {
			// cannot resolve without entry or project context
			return new IRuntimeBuildpathEntry[0];
		}
		IBuildpathContainer container = DLTKCore
				.getBuildpathContainer(entry.getPath(), project);
		if (container == null) {
			abort(MessageFormat.format(
					LaunchingMessages.ScriptRuntime_Could_not_resolve_classpath_container___0__1,
					entry.getPath().toString()), null);
			// execution will not reach here - exception will be thrown
			return null;
		}
		IBuildpathEntry[] cpes = container.getBuildpathEntries();
		int property = -1;
		switch (container.getKind()) {
		case IBuildpathContainer.K_APPLICATION:
			property = IRuntimeBuildpathEntry.USER_ENTRY;
			break;
		case IBuildpathContainer.K_DEFAULT_SYSTEM:
			property = IRuntimeBuildpathEntry.STANDARD_ENTRY;
			break;
		case IBuildpathContainer.K_SYSTEM:
			property = IRuntimeBuildpathEntry.BOOTSTRAP_ENTRY;
			break;
		}
		List<IRuntimeBuildpathEntry> resolved = new ArrayList<>(cpes.length);
		List<IScriptProject> projects = fgProjects.get();
		Integer count = fgEntryCount.get();
		if (projects == null) {
			projects = new ArrayList<>();
			fgProjects.set(projects);
			count = Integer.valueOf(0);
		}
		int intCount = count.intValue();
		intCount++;
		fgEntryCount.set(Integer.valueOf(intCount));
		try {
			for (int i = 0; i < cpes.length; i++) {
				IBuildpathEntry cpe = cpes[i];
				if (cpe.getEntryKind() == IBuildpathEntry.BPE_PROJECT) {
					IProject p = ResourcesPlugin.getWorkspace().getRoot()
							.getProject(cpe.getPath().segment(0));
					IScriptProject jp = DLTKCore.create(p);
					if (!projects.contains(jp)) {
						projects.add(jp);
						IRuntimeBuildpathEntry buildpath = newDefaultProjectBuildpathEntry(
								jp);
						IRuntimeBuildpathEntry[] entries = resolveRuntimeBuildpathEntry(
								buildpath, jp);
						for (int j = 0; j < entries.length; j++) {
							IRuntimeBuildpathEntry e = entries[j];
							if (!resolved.contains(e)) {
								resolved.add(entries[j]);
							}
						}
					}
				} else {
					IRuntimeBuildpathEntry e = newRuntimeBuildpathEntry(cpe);
					if (!resolved.contains(e)) {
						resolved.add(e);
					}
				}
			}
		} finally {
			intCount--;
			if (intCount == 0) {
				fgProjects.set(null);
				fgEntryCount.set(null);
			} else {
				fgEntryCount.set(Integer.valueOf(intCount));
			}
		}
		// set buildpath property
		IRuntimeBuildpathEntry[] result = new IRuntimeBuildpathEntry[resolved
				.size()];
		for (int i = 0; i < result.length; i++) {
			result[i] = resolved.get(i);
			result[i].setBuildpathProperty(property);
		}
		return result;
	}

	/**
	 * Returns resolved entries for the given entry in the context of the given
	 * launch configuration. If the entry is of kind <code>CONTAINER</code>,
	 * container resolvers are consulted. Otherwise, the given entry is
	 * returned.
	 * <p>
	 * If the given entry is a container, and a resolver is not registered,
	 * resolved runtime buildpath entries are calculated from the associated
	 * container buildpath entries, in the context of the project associated
	 * with the given launch configuration.
	 * </p>
	 *
	 * @param entry
	 *            runtime classpath entry
	 * @param configuration
	 *            launch configuration
	 * @return resolved runtime classpath entry
	 * @exception CoreException
	 *                if unable to resolve
	 * @see IRuntimeBuildpathEntryResolver
	 *
	 */
	public static IRuntimeBuildpathEntry[] resolveRuntimeBuildpathEntry(
			IRuntimeBuildpathEntry entry, ILaunchConfiguration configuration)
			throws CoreException {
		switch (entry.getType()) {
		case IRuntimeBuildpathEntry.PROJECT:
			// if the project has multiple output locations, they must be
			// returned
			IResource resource = entry.getResource();
			if (resource instanceof IProject) {
				IProject p = (IProject) resource;
				IScriptProject project = DLTKCore.create(p);
				if (project == null || !p.isOpen() || !project.exists()) {
					return new IRuntimeBuildpathEntry[0];
				}
			} else {
				abort(MessageFormat.format(
						LaunchingMessages.ScriptRuntime_Buildpath_references_non_existant_project___0__3,
						entry.getPath().lastSegment()), null);
			}
			break;
		case IRuntimeBuildpathEntry.CONTAINER:
			IRuntimeBuildpathEntryResolver resolver = getContainerResolver(
					entry.getContainerName());
			if (resolver == null) {
				return computeDefaultContainerEntries(entry, configuration);
			}
			return resolver.resolveRuntimeBuildpathEntry(entry, configuration);
		case IRuntimeBuildpathEntry.ARCHIVE:
			// verify the archive exists
			String location = entry.getLocation();
			if (location == null) {
				abort(MessageFormat.format(
						LaunchingMessages.ScriptRuntime_Buildpath_references_non_existant_archive___0__4,
						entry.getPath().toString()), null);
			}
			IFileHandle fileHandle;
			IPath path = entry.getPath();
			if (EnvironmentPathUtils.isFull(path))
				fileHandle = EnvironmentPathUtils.getFile(path);
			else
				fileHandle = LocalEnvironment.getInstance().getFile(path);
			if (fileHandle == null || !fileHandle.exists()) {
				abort(MessageFormat.format(
						LaunchingMessages.ScriptRuntime_Buildpath_references_non_existant_archive___0__4,
						entry.getPath().toString()), null);
			}
			break;
		case IRuntimeBuildpathEntry.OTHER:
			resolver = getContributedResolver(
					((IRuntimeBuildpathEntry2) entry).getTypeId());
			return resolver.resolveRuntimeBuildpathEntry(entry, configuration);
		default:
			break;
		}
		return new IRuntimeBuildpathEntry[] { entry };
	}

	/**
	 * Returns resolved entries for the given entry in the context of the given
	 * script project. If the entry is of kind <code>CONTAINER</code>, container
	 * resolvers are consulted.
	 * <p>
	 * If the given entry is a container, and a resolver is not registered,
	 * resolved runtime classpath entries are calculated from the associated
	 * container classpath entries, in the context of the given project.
	 * </p>
	 *
	 * @param entry
	 *            runtime classpath entry
	 * @param project
	 *            Script project context
	 * @return resolved runtime classpath entry
	 * @exception CoreException
	 *                if unable to resolve
	 * @see IRuntimeBuildpathEntryResolver
	 *
	 */
	public static IRuntimeBuildpathEntry[] resolveRuntimeBuildpathEntry(
			IRuntimeBuildpathEntry entry, IScriptProject project)
			throws CoreException {
		switch (entry.getType()) {
		case IRuntimeBuildpathEntry.CONTAINER:
			IRuntimeBuildpathEntryResolver resolver = getContainerResolver(
					entry.getContainerName());
			if (resolver == null) {
				return computeDefaultContainerEntries(entry, project);
			}
			return resolver.resolveRuntimeBuildpathEntry(entry, project);
		case IRuntimeBuildpathEntry.OTHER:
			resolver = getContributedResolver(
					((IRuntimeBuildpathEntry2) entry).getTypeId());
			return resolver.resolveRuntimeBuildpathEntry(entry, project);
		default:
			break;
		}
		return new IRuntimeBuildpathEntry[] { entry };
	}

	/**
	 * Computes and returns the unresolved build path for the given launch
	 * configuration. Variable and container entries are unresolved.
	 *
	 * @param configuration
	 *            launch configuration
	 * @return unresolved runtime buildpath entries
	 * @exception CoreException
	 *                if unable to compute the buildpath
	 */
	public static IRuntimeBuildpathEntry[] computeUnresolvedRuntimeBuildpath(
			ILaunchConfiguration configuration) throws CoreException {
		return getBuildpathProvider(configuration)
				.computeUnresolvedBuildpath(configuration);
	}

	/**
	 * Resolves the given buildpath, returning the resolved buildpath in the
	 * context of the given launch configuration.
	 *
	 * @param entries
	 *            unresolved buildpath
	 * @param configuration
	 *            launch configuration
	 * @return resolved runtime buildpath entries
	 * @exception CoreException
	 *                if unable to compute the buildpath
	 */
	public static IRuntimeBuildpathEntry[] resolveRuntimeBuildpath(
			IRuntimeBuildpathEntry[] entries,
			ILaunchConfiguration configuration) throws CoreException {
		return getBuildpathProvider(configuration).resolveBuildpath(entries,
				configuration);
	}

	/**
	 * Returns all registered runtime buildpath entry resolvers.
	 */
	private static Map<String, IRuntimeBuildpathEntryResolver> getEntryResolvers() {
		if (fgRuntimeBuildpathEntryResolvers == null) {
			initializeResolvers();
		}
		return fgRuntimeBuildpathEntryResolvers;
	}

	/**
	 * Returns the resolver registered for the given contributed buildpath entry
	 * type.
	 *
	 * @param typeId
	 *            the id of the contributed buildpath entry
	 * @return the resolver registered for the given buildpath entry
	 */
	private static IRuntimeBuildpathEntryResolver getContributedResolver(
			String typeId) {
		IRuntimeBuildpathEntryResolver resolver = getEntryResolvers()
				.get(typeId);
		if (resolver == null) {
			return new DefaultEntryResolver();
		}
		return resolver;
	}

	/**
	 * Computes the default application buildpath entries for the given project.
	 *
	 * @param jproject
	 *            The project to compute the buildpath for
	 * @return The computed buildpath. May be empty, but not null.
	 * @throws CoreException
	 *             if unable to compute the default buildpath
	 */
	public static String[] computeDefaultRuntimeClassPath(
			IScriptProject jproject) throws CoreException {
		IRuntimeBuildpathEntry[] unresolved = computeUnresolvedRuntimeBuildpath(
				jproject);
		// 1. remove bootpath entries
		// 2. resolve & translate to local file system paths
		List<String> resolved = new ArrayList<>(unresolved.length);
		for (int i = 0; i < unresolved.length; i++) {
			IRuntimeBuildpathEntry entry = unresolved[i];
			if (entry
					.getBuildpathProperty() == IRuntimeBuildpathEntry.USER_ENTRY) {
				IRuntimeBuildpathEntry[] entries = resolveRuntimeBuildpathEntry(
						entry, jproject);
				for (int j = 0; j < entries.length; j++) {
					String location = entries[j].getLocation();
					if (location != null) {
						resolved.add(location);
					}
				}
			}
		}
		return resolved.toArray(new String[resolved.size()]);
	}

	public static ISourceContainer[] getSourceContainers(
			IRuntimeBuildpathEntry[] resolved) {
		return ScriptSourceLookupUtil.translate(resolved);
	}

	public static IRuntimeBuildpathEntry[] computeUnresolvedSourceBuildpath(
			ILaunchConfiguration configuration) throws CoreException {
		return getScriptpathProvider(configuration)
				.computeUnresolvedBuildpath(configuration);
	}

}