/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Frits Jalvingh - Contribution for Bug 459831 - [launching] Support attaching
 *     	external annotations to a JRE container
 *******************************************************************************/
package org.eclipse.jdt.launching;


import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;

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.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.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.BundleDefaultsScope;
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.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IModuleDescription;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.launching.CompositeId;
import org.eclipse.jdt.internal.launching.DefaultEntryResolver;
import org.eclipse.jdt.internal.launching.DefaultProjectClasspathEntry;
import org.eclipse.jdt.internal.launching.EEVMInstall;
import org.eclipse.jdt.internal.launching.EEVMType;
import org.eclipse.jdt.internal.launching.JREContainerInitializer;
import org.eclipse.jdt.internal.launching.JavaSourceLookupUtil;
import org.eclipse.jdt.internal.launching.LaunchingMessages;
import org.eclipse.jdt.internal.launching.LaunchingPlugin;
import org.eclipse.jdt.internal.launching.RuntimeClasspathEntry;
import org.eclipse.jdt.internal.launching.RuntimeClasspathEntryResolver;
import org.eclipse.jdt.internal.launching.RuntimeClasspathProvider;
import org.eclipse.jdt.internal.launching.SocketAttachConnector;
import org.eclipse.jdt.internal.launching.StandardVMType;
import org.eclipse.jdt.internal.launching.VMDefinitionsContainer;
import org.eclipse.jdt.internal.launching.VMListener;
import org.eclipse.jdt.internal.launching.VariableClasspathEntry;
import org.eclipse.jdt.internal.launching.environments.EnvironmentsManager;
import org.eclipse.jdt.launching.environments.ExecutionEnvironmentDescription;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
import org.eclipse.osgi.util.NLS;
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;

/**
 * The central access point for launching support. This class manages
 * the registered VM types contributed through the
 * <code>"org.eclipse.jdt.launching.vmType"</code> extension point.
 * As well, this class provides VM install change notification,
 * and computes class paths and source lookup paths for launch
 * configurations.
 * <p>
 * This class provides static methods only.
 * </p>
 * @noinstantiate This class is not intended to be instantiated by clients.
 */
public final class JavaRuntime {

	/**
	 * Classpath variable name used for the default JRE's library
	 * (value <code>"JRE_LIB"</code>).
	 */
	public static final String JRELIB_VARIABLE= "JRE_LIB"; //$NON-NLS-1$

	/**
	 * Classpath variable name used for the default JRE's library source
	 * (value <code>"JRE_SRC"</code>).
	 */
	public static final String JRESRC_VARIABLE= "JRE_SRC"; //$NON-NLS-1$

	/**
	 * Classpath variable name used for the default JRE's library source root
	 * (value <code>"JRE_SRCROOT"</code>).
	 */
	public static final String JRESRCROOT_VARIABLE= "JRE_SRCROOT"; //$NON-NLS-1$

	/**
	 * Simple identifier constant (value <code>"runtimeClasspathEntryResolvers"</code>) for the
	 * runtime classpath entry resolvers extension point.
	 *
	 * @since 2.0
	 */
	public static final String EXTENSION_POINT_RUNTIME_CLASSPATH_ENTRY_RESOLVERS= "runtimeClasspathEntryResolvers";	 //$NON-NLS-1$

	/**
	 * Simple identifier constant (value <code>"classpathProviders"</code>) for the
	 * runtime classpath providers extension point.
	 *
	 * @since 2.0
	 */
	public static final String EXTENSION_POINT_RUNTIME_CLASSPATH_PROVIDERS= "classpathProviders";	 //$NON-NLS-1$

	/**
	 * Simple identifier constant (value <code>"executionEnvironments"</code>) for the
	 * execution environments extension point.
	 *
	 * @since 3.2
	 */
	public static final String EXTENSION_POINT_EXECUTION_ENVIRONMENTS= "executionEnvironments";	 //$NON-NLS-1$

	/**
	 * Simple identifier constant (value <code>"vmInstalls"</code>) for the
	 * VM installs extension point.
	 *
	 * @since 3.2
	 */
	public static final String EXTENSION_POINT_VM_INSTALLS = "vmInstalls";	 //$NON-NLS-1$

	/**
	 * Simple identifier constant (value <code>"libraryLocationResolvers"</code>) for the
	 * Library Resolvers extension point
	 *
	 * @since 3.7
	 */
	public static final String EXTENSION_POINT_LIBRARY_LOCATION_RESOLVERS = "libraryLocationResolvers"; //$NON-NLS-1$

	/**
	 * Classpath container used for a project's JRE
	 * (value <code>"org.eclipse.jdt.launching.JRE_CONTAINER"</code>). A
	 * container is resolved in the context of a specific Java project, to one
	 * or more system libraries contained in a JRE. The container can have zero
	 * or two path segments following the container name. When no segments
	 * follow the container name, the workspace default JRE is used to build a
	 * project. Otherwise the segments identify a specific JRE used to build a
	 * project:
	 * <ol>
	 * <li>VM Install Type Identifier - identifies the type of JRE used to build the
	 * 	project. For example, the standard VM.</li>
	 * <li>VM Install Name - a user defined name that identifies that a specific VM
	 * 	of the above kind. For example, <code>IBM 1.3.1</code>. This information is
	 *  shared in a projects classpath file, so teams must agree on JRE naming
	 * 	conventions.</li>
	 * </ol>
	 * <p>
	 * Since 3.2, 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>
	 * @since 2.0
	 */
	public static final String JRE_CONTAINER = LaunchingPlugin.getUniqueIdentifier() + ".JRE_CONTAINER"; //$NON-NLS-1$

	/**
	 * Marker type identifier for JRE container problems.
	 *
	 * @since 3.6
	 */
	public static final String JRE_CONTAINER_MARKER = LaunchingPlugin.getUniqueIdentifier() + ".jreContainerMarker"; //$NON-NLS-1$

	/**
	 * A status code indicating that a JRE could not be resolved for a project.
	 * When a JRE 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 Java project for which the path could not be
	 * resolved. The status handler must return an <code>IVMInstall</code> or <code>null</code>.
	 * The container resolver will re-set the project's classpath if required.
	 *
	 * @since 2.0
	 */
	public static final int ERR_UNABLE_TO_RESOLVE_JRE = 160;

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

	/**
	 * Preference key for the String of XML that defines all installed VMs.
	 *
	 * @since 2.1
	 */
	public static final String PREF_VM_XML = LaunchingPlugin.getUniqueIdentifier() + ".PREF_VM_XML"; //$NON-NLS-1$

	/**
	 * Preference key for the default problem severity when an execution environment is bound
	 * to a project's build path for which there is no strictly compatible JRE available in the
	 * workspace. Value is one of {@link JavaCore#ERROR}, {@link JavaCore#WARNING}, or
	 * {@link JavaCore#IGNORE}
	 *
	 * @since 3.5
	 */
	public static final String PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE = LaunchingPlugin.getUniqueIdentifier() + ".PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE"; //$NON-NLS-1$

	/**
	 * Unique identifier constant (value <code>"org.eclipse.jdt.launching"</code>)
	 * for the Java launching plug-in.
	 *
	 * @since 3.5
	 */
	public static final String ID_PLUGIN = LaunchingPlugin.ID_PLUGIN;

	/**
	 * Default launch/connect timeout (milliseconds).
	 *
	 * @since 2.0
	 */
	public static final int DEF_CONNECT_TIMEOUT = 20000;

	/**
	 * Attribute key for a process property. The class
	 * <code>org.eclipse.debug.core.model.IProcess</code> allows attaching
	 * String properties to processes.
	 * The value of this attribute is the command line a process
	 * was launched with. Implementers of <code>IVMRunner</code> should use
	 * this attribute key to attach the command lines to the processes they create.
	 *
	 * @deprecated - use <code>IProcess.ATTR_CMDLINE</code>
	 */
	@Deprecated
	public final static String ATTR_CMDLINE= LaunchingPlugin.getUniqueIdentifier() + ".launcher.cmdLine"; //$NON-NLS-1$

	/**
	 * Boolean preference controlling whether only exported entries should even be included when the runtime classpath is computed
	 * @since 3.7
	 */
	public static final String PREF_ONLY_INCLUDE_EXPORTED_CLASSPATH_ENTRIES = ID_PLUGIN + ".only_include_exported_classpath_entries"; //$NON-NLS-1$

	/**
	 * Attribute key for a classpath attribute referencing a
	 * list of shared libraries that should appear on the
	 * <code>-Djava.library.path</code> system property.
	 * <p>
	 * The factory methods <code>newLibraryPathsAttribute(String[])</code>
	 * and <code>getLibraryPaths(IClasspathAttribute)</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>
	 * @since 3.1
	 * @see org.eclipse.jdt.core.IClasspathAttribute
	 */
	public static final String CLASSPATH_ATTR_LIBRARY_PATH_ENTRY =  LaunchingPlugin.getUniqueIdentifier() + ".CLASSPATH_ATTR_LIBRARY_PATH_ENTRY"; //$NON-NLS-1$

	// lock for VM initialization
	private static Object fgVMLock = new Object();
	private static boolean fgInitializingVMs = false;

	private static HashSet<Object> fgVMTypes = null;
	private static String fgDefaultVMId = null;
	private static String fgDefaultVMConnectorId = null;

	/**
	 * Resolvers keyed by variable name, container id,
	 * and runtime classpath entry id.
	 */
	private static Map<String, IRuntimeClasspathEntryResolver> fgVariableResolvers = null;
	private static Map<String, IRuntimeClasspathEntryResolver> fgContainerResolvers = null;
	private static Map<String, RuntimeClasspathEntryResolver> fgRuntimeClasspathEntryResolvers = null;

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

	/**
	 * Default classpath and source path providers.
	 */
	private static IRuntimeClasspathProvider fgDefaultClasspathProvider = new StandardClasspathProvider();
	private static IRuntimeClasspathProvider fgDefaultSourcePathProvider = new StandardSourcePathProvider();

	/**
	 * VM change listeners
	 */
	private static ListenerList<IVMInstallChangedListener> fgVMListeners = new ListenerList<>();

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

    /**
     *  Set of IDs of VMs contributed via vmInstalls extension point.
     */
    private static Set<String> fgContributedVMs = new HashSet<>();

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

	/**
	 * Initializes VM type extensions.
	 */
	private static void initializeVMTypeExtensions() {
		IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(LaunchingPlugin.ID_PLUGIN, "vmInstallTypes"); //$NON-NLS-1$
		if(extensionPoint != null) {
			IConfigurationElement[] configs = extensionPoint.getConfigurationElements();
			MultiStatus status = new MultiStatus(LaunchingPlugin.getUniqueIdentifier(), IStatus.OK, "Exceptions occurred", null);  //$NON-NLS-1$
			fgVMTypes = new HashSet<>();
			for (int i= 0; i < configs.length; i++) {
				try {
					fgVMTypes.add(configs[i].createExecutableExtension("class")); //$NON-NLS-1$
				}
				catch (CoreException e) {status.add(e.getStatus());}
			}
			if (!status.isOK()) {
				//only happens on a CoreException
				LaunchingPlugin.log(status);
			}
		}
		else {
			LaunchingPlugin.log(new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), "VM Install extension point not found", null)); //$NON-NLS-1$
		}
	}

	/**
	 * Returns the VM assigned to build the given Java project.
	 * The project must exist. The VM assigned to a project is
	 * determined from its build path.
	 *
	 * @param project the project to retrieve the VM from
	 * @return the VM instance that is assigned to build the given Java project
	 * 		   Returns <code>null</code> if no VM is referenced on the project's build path.
	 * @throws CoreException if unable to determine the project's VM install
	 */
	public static IVMInstall getVMInstall(IJavaProject project) throws CoreException {
		// check the classpath
		IVMInstall vm = null;
		IClasspathEntry[] classpath = project.getRawClasspath();
		IRuntimeClasspathEntryResolver resolver = null;
		IClasspathEntry entry = null;
		for (int i = 0; i < classpath.length; i++) {
			entry = classpath[i];
			switch (entry.getEntryKind()) {
				case IClasspathEntry.CPE_VARIABLE:
					resolver = getVariableResolver(entry.getPath().segment(0));
					if (resolver != null) {
						vm = resolver.resolveVMInstall(entry);
					}
					break;
				case IClasspathEntry.CPE_CONTAINER:
					resolver = getContainerResolver(entry.getPath().segment(0));
					if (resolver != null) {
						vm = resolver.resolveVMInstall(entry);
					}
					break;
			}
			if (vm != null) {
				return vm;
			}
		}
		return null;
	}

	/**
	 * Returns the VM install type with the given unique id.
	 * @param id the VM install type unique id
	 * @return	The VM install type for the given id, or <code>null</code> if no
	 * 			VM install type with the given id is registered.
	 */
	public static IVMInstallType getVMInstallType(String id) {
		IVMInstallType[] vmTypes= getVMInstallTypes();
		for (int i= 0; i < vmTypes.length; i++) {
			if (vmTypes[i].getId().equals(id)) {
				return vmTypes[i];
			}
		}
		return null;
	}

	/**
	 * Sets a VM as the system-wide default VM, and notifies registered VM install
	 * change listeners of the change.
	 *
	 * @param vm	The VM to make the default. May be <code>null</code> to clear
	 * 				the default.
	 * @param monitor progress monitor or <code>null</code>
	 * @throws CoreException if trying to set the default VM install encounters problems
	 */
	public static void setDefaultVMInstall(IVMInstall vm, IProgressMonitor monitor) throws CoreException {
		setDefaultVMInstall(vm, monitor, true);
	}

	/**
	 * Sets a VM as the system-wide default VM, and notifies registered VM install
	 * change listeners of the change.
	 *
	 * @param vm	The VM 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 VM.
	 * @throws CoreException if trying to set the default VM install encounters problems
	 * @since 2.1
	 */
	public static void setDefaultVMInstall(IVMInstall vm, IProgressMonitor monitor, boolean savePreference) throws CoreException {
		IVMInstall previous = null;
		if (fgDefaultVMId != null) {
			previous = getVMFromCompositeId(fgDefaultVMId);
		}
		fgDefaultVMId= getCompositeIdFromVM(vm);
		if (savePreference) {
			saveVMConfiguration();
		}
		IVMInstall current = null;
		if (fgDefaultVMId != null) {
			current = getVMFromCompositeId(fgDefaultVMId);
		}
		if (previous != current) {
			notifyDefaultVMChanged(previous, current);
		}
	}

	/**
	 * Sets a VM connector as the system-wide default VM. This setting is persisted when
	 * saveVMConfiguration is called.
	 * @param	connector The connector to make the default. May be <code>null</code> to clear
	 * 				the default.
	 * @param monitor The progress monitor to use
	 * @since 2.0
	 * @throws CoreException Thrown if saving the new default setting fails
	 */
	public static void setDefaultVMConnector(IVMConnector connector, IProgressMonitor monitor) throws CoreException {
		fgDefaultVMConnectorId= connector.getIdentifier();
		saveVMConfiguration();
	}

	/**
	 * Return the default VM set with <code>setDefaultVM()</code>.
	 * @return	Returns the default VM. May return <code>null</code> when no default
	 * 			VM was set or when the default VM has been disposed.
	 */
	public static IVMInstall getDefaultVMInstall() {
		IVMInstall install= getVMFromCompositeId(getDefaultVMId());
		if (install != null) {
			File location = install.getInstallLocation();
			if (location != null) {
				if (location.exists()) {
					return install;
				}
			}
		}
		// if the default JRE goes missing, re-detect
		if (install != null) {
			install.getVMInstallType().disposeVMInstall(install.getId());
		}
		synchronized (fgVMLock) {
			fgDefaultVMId = null;
			fgVMTypes = null;
			initializeVMs();
		}
		return getVMFromCompositeId(getDefaultVMId());
	}

	/**
	 * Return the default VM connector.
	 * @return	Returns the default VM connector.
	 * @since 2.0
	 */
	public static IVMConnector getDefaultVMConnector() {
		String id = getDefaultVMConnectorId();
		IVMConnector connector = null;
		if (id != null) {
			connector = getVMConnector(id);
		}
		if (connector == null) {
			connector = new SocketAttachConnector();
		}
		return connector;
	}

	/**
	 * Returns the list of registered VM types. VM types are registered via
	 * <code>"org.eclipse.jdt.launching.vmTypes"</code> extension point.
	 * Returns an empty list if there are no registered VM types.
	 *
	 * @return the list of registered VM types
	 */
	public static IVMInstallType[] getVMInstallTypes() {
		initializeVMs();
		return fgVMTypes.toArray(new IVMInstallType[fgVMTypes.size()]);
	}

	/**
	 * Returns the default VM id determined during the initialization of the VM types
	 * @return the id of the default VM
	 */
	private static String getDefaultVMId() {
		initializeVMs();
		return fgDefaultVMId;
	}

	/**
	 * Returns the default VM connector id determined during the initialization of the VM types
	 * @return the id of the default VM connector
	 */
	private static String getDefaultVMConnectorId() {
		initializeVMs();
		return fgDefaultVMConnectorId;
	}

	/**
	 * Returns a String that uniquely identifies the specified VM across all VM types.
	 *
	 * @param vm the instance of IVMInstallType to be identified
	 * @return the unique identifier for the specified VM
	 *
	 * @since 2.1
	 */
	public static String getCompositeIdFromVM(IVMInstall vm) {
		if (vm == null) {
			return null;
		}
		IVMInstallType vmType = vm.getVMInstallType();
		String typeID = vmType.getId();
		CompositeId id = new CompositeId(new String[] { typeID, vm.getId() });
		return id.toString();
	}

	/**
	 * Return the VM corresponding to the specified composite Id.  The id uniquely
	 * identifies a VM across all VM types.
	 *
	 * @param idString the composite id that specifies an instance of IVMInstall
	 * @return the VM corresponding to the specified composite Id.
	 *
	 * @since 2.1
	 */
	public static IVMInstall getVMFromCompositeId(String idString) {
		if (idString == null || idString.length() == 0) {
			return null;
		}
		CompositeId id= CompositeId.fromString(idString);
		if (id.getPartCount() == 2) {
			IVMInstallType vmType= getVMInstallType(id.get(0));
			if (vmType != null) {
				return vmType.findVMInstall(id.get(1));
			}
		}
		return null;
	}

	/**
	 * Returns a new runtime classpath entry for the given expression that
	 * may contain string substitution variable references. The resulting expression
	 * refers to an archive (jar or directory) containing class files.
	 *
	 * @param expression an expression that resolves to the location of an archive
	 * @return runtime classpath entry
	 * @since 3.0
	 */
	public static IRuntimeClasspathEntry newStringVariableClasspathEntry(String expression) {
		return new VariableClasspathEntry(expression);
	}

	/**
	 * Returns a new runtime classpath entry containing the default classpath
	 * for the specified Java project.
	 *
	 * @param project Java project
	 * @return runtime classpath entry
	 * @since 3.0
	 */
	public static IRuntimeClasspathEntry newDefaultProjectClasspathEntry(IJavaProject project) {
		return new DefaultProjectClasspathEntry(project);
	}

	/**
	 * Returns a new runtime classpath entry for the given project.
	 *
	 * @param project Java project
	 * @return runtime classpath entry
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry newProjectRuntimeClasspathEntry(IJavaProject project) {
		return newRuntimeClasspathEntry(JavaCore.newProjectEntry(project.getProject().getFullPath()));
	}

	/**
	 * Returns a new runtime classpath entry for the given project.
	 *
	 * @param project
	 *            Java project
	 * @param classpathProperty
	 *            the type of entry - one of <code>USER_CLASSES</code>, <code>BOOTSTRAP_CLASSES</code>,<code>STANDARD_CLASSES</code>,
	 *            <code>MODULE_PATH</code> or <code>CLASS_PATH</code>
	 * @return runtime classpath entry
	 * @since 3.10
	 */
	public static IRuntimeClasspathEntry newProjectRuntimeClasspathEntry(IJavaProject project, int classpathProperty) {
		return newRuntimeClasspathEntry(JavaCore.newProjectEntry(project.getProject().getFullPath()), classpathProperty);
	}


	/**
	 * Returns a new runtime classpath entry for the given archive.
	 *
	 * @param resource archive resource
	 * @return runtime classpath entry
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry newArchiveRuntimeClasspathEntry(IResource resource) {
		return newRuntimeClasspathEntry(JavaCore.newLibraryEntry(resource.getFullPath(), null, null));
	}

	/**
	 * Returns a new runtime classpath entry for the given archive(possibly external).
	 *
	 * @param path
	 *            absolute path to an archive
	 * @param classpathProperty
	 *            the type of entry - one of <code>USER_CLASSES</code>, <code>BOOTSTRAP_CLASSES</code>,<code>STANDARD_CLASSES</code>,
	 *            <code>MODULE_PATH</code> or <code>CLASS_PATH</code>
	 * @return runtime classpath entry
	 * @since 3.10
	 */
	public static IRuntimeClasspathEntry newArchiveRuntimeClasspathEntry(IPath path, int classpathProperty) {
		return newRuntimeClasspathEntry(JavaCore.newLibraryEntry(path, null, null), classpathProperty);
	}

	/**
	 * Returns a new runtime classpath entry for the given archive (possibly
	 * external).
	 *
	 * @param path absolute path to an archive
	 * @return runtime classpath entry
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry newArchiveRuntimeClasspathEntry(IPath path) {
		return newRuntimeClasspathEntry(JavaCore.newLibraryEntry(path, null, null));
	}

	/**
	 * Returns a new runtime classpath entry for the given archive (possibly external).
	 *
	 * @param path
	 *            absolute path to an archive
	 * @param sourceAttachmentPath
	 *            the absolute path of the corresponding source archive or folder, or <code>null</code> if none. Note, since 3.0, an empty path is
	 *            allowed to denote no source attachment. and will be automatically converted to <code>null</code>. Since 3.4, this path can also
	 *            denote a path external to the workspace.
	 * @param sourceAttachmentRootPath
	 *            the location of the root of the source files within the source archive or folder or <code>null</code> if this location should be
	 *            automatically detected.
	 * @param accessRules
	 *            the possibly empty list of access rules for this entry
	 * @param extraAttributes
	 *            the possibly empty list of extra attributes to persist with this entry
	 * @param isExported
	 *            indicates whether this entry is contributed to dependent projects in addition to the output location
	 * @return runtime classpath entry
	 * @since 3.10
	 */
	public static IRuntimeClasspathEntry newArchiveRuntimeClasspathEntry(IPath path, IPath sourceAttachmentPath, IPath sourceAttachmentRootPath, IAccessRule[] accessRules, IClasspathAttribute[] extraAttributes, boolean isExported) {
		return newRuntimeClasspathEntry(JavaCore.newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, accessRules, extraAttributes, isExported));
	}

	/**
	 * Returns a new runtime classpath entry for the classpath
	 * variable with the given path.
	 *
	 * @param path variable path; first segment is the name of the variable;
	 * 	trailing segments are appended to the resolved variable value
	 * @return runtime classpath entry
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry newVariableRuntimeClasspathEntry(IPath path) {
		return newRuntimeClasspathEntry(JavaCore.newVariableEntry(path, null, null));
	}

	/**
	 * Returns a runtime classpath entry for the given container path with the given
	 * classpath property.
	 *
	 * @param path container path
	 * @param classpathProperty the type of entry - one of <code>USER_CLASSES</code>,
	 * 	<code>BOOTSTRAP_CLASSES</code>,<code>STANDARD_CLASSES</code>, <code>MODULE_PATH</code>
	 *  or <code>CLASS_PATH</code>
	 * @return runtime classpath entry
	 * @exception CoreException if unable to construct a runtime classpath entry
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry newRuntimeContainerClasspathEntry(IPath path, int classpathProperty) throws CoreException {
		return newRuntimeContainerClasspathEntry(path, classpathProperty, null);
	}

	/**
	 * Returns a runtime classpath entry for the given container path with the given
	 * classpath property to be resolved in the context of the given Java project.
	 *
	 * @param path container path
	 * @param classpathProperty the type of entry - one of <code>USER_CLASSES</code>,
	 * 	<code>BOOTSTRAP_CLASSES</code>, or <code>STANDARD_CLASSES</code>
	 * @param project Java 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 classpath entry
	 * @exception CoreException if unable to construct a runtime classpath entry
	 * @since 3.0
	 */
	public static IRuntimeClasspathEntry newRuntimeContainerClasspathEntry(IPath path, int classpathProperty, IJavaProject project) throws CoreException {
		RuntimeClasspathEntry entry = new RuntimeClasspathEntry(JavaCore.newContainerEntry(path), classpathProperty);
		entry.setJavaProject(project);
		return entry;
	}

	/**
	 * Returns a runtime classpath entry constructed from the given memento.
	 *
	 * @param memento a memento for a runtime classpath entry
	 * @return runtime classpath entry
	 * @exception CoreException if unable to construct a runtime classpath entry
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry newRuntimeClasspathEntry(String memento) throws CoreException {
		try {
			Element root = null;
			DocumentBuilder parser = LaunchingPlugin.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 RuntimeClasspathEntry(root);
			}
			// get the extension & create a new one
			IRuntimeClasspathEntry2 entry = LaunchingPlugin.getDefault().newRuntimeClasspathEntry(id);
			NodeList list = root.getChildNodes();
			Node node = null;
			Element element = null;
			for (int i = 0; i < list.getLength(); i++) {
				node = list.item(i);
				if (node.getNodeType() == Node.ELEMENT_NODE) {
					element = (Element)node;
					if ("memento".equals(element.getNodeName())) { //$NON-NLS-1$
						entry.initializeFrom(element);
					}
				}
			}
			return entry;
		} catch (SAXException e) {
			abort(LaunchingMessages.JavaRuntime_32, e);
		} catch (IOException e) {
			abort(LaunchingMessages.JavaRuntime_32, e);
		}
		return null;
	}

	/**
	 * Returns a runtime classpath entry that corresponds to the given
	 * classpath entry. The classpath entry may not be of type <code>CPE_SOURCE</code>
	 * or <code>CPE_CONTAINER</code>.
	 *
	 * @param entry a classpath entry
	 * @return runtime classpath entry
	 * @since 2.0
	 */
	private static IRuntimeClasspathEntry newRuntimeClasspathEntry(IClasspathEntry entry) {
		return new RuntimeClasspathEntry(entry);
	}

	/**
	 * Returns a runtime classpath entry that corresponds to the given classpath entry. The classpath entry may not be of type <code>CPE_SOURCE</code>
	 * or <code>CPE_CONTAINER</code>.
	 *
	 * @param entry
	 *            a classpath entry
	 * @return runtime classpath entry
	 * @since 2.0
	 */
	private static IRuntimeClasspathEntry newRuntimeClasspathEntry(IClasspathEntry entry, int classPathProperty) {
		return new RuntimeClasspathEntry(entry, classPathProperty);
	}

	/**
	 * Computes and returns the default unresolved runtime classpath for the
	 * given project.
	 *
	 * @param project the {@link IJavaProject} to compute the unresolved runtime classpath for
	 * @return runtime classpath entries
	 * @exception CoreException if unable to compute the runtime classpath
	 * @see IRuntimeClasspathEntry
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry[] computeUnresolvedRuntimeClasspath(IJavaProject project) throws CoreException {
		IClasspathEntry[] entries = project.getRawClasspath();
		List<IRuntimeClasspathEntry> classpathEntries = new ArrayList<>(3);
		for (int i = 0; i < entries.length; i++) {
			IClasspathEntry entry = entries[i];
			switch (entry.getEntryKind()) {
				case IClasspathEntry.CPE_CONTAINER:
					IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
					if (container != null) {
						switch (container.getKind()) {
							case IClasspathContainer.K_APPLICATION:
								// don't look at application entries
								break;
							case IClasspathContainer.K_DEFAULT_SYSTEM:
								classpathEntries.add(newRuntimeContainerClasspathEntry(container.getPath(), IRuntimeClasspathEntry.STANDARD_CLASSES, project));
								break;
							case IClasspathContainer.K_SYSTEM:
								classpathEntries.add(newRuntimeContainerClasspathEntry(container.getPath(), IRuntimeClasspathEntry.BOOTSTRAP_CLASSES, project));
								break;
						}
					}
					break;
				case IClasspathEntry.CPE_VARIABLE:
					if (JRELIB_VARIABLE.equals(entry.getPath().segment(0))) {
						IRuntimeClasspathEntry jre = newVariableRuntimeClasspathEntry(entry.getPath());
						jre.setClasspathProperty(IRuntimeClasspathEntry.STANDARD_CLASSES);
						classpathEntries.add(jre);
					}
					break;
				default:
					break;
			}
		}
		classpathEntries.add(newDefaultProjectClasspathEntry(project));
		return classpathEntries.toArray(new IRuntimeClasspathEntry[classpathEntries.size()]);
	}

	/**
	 * Computes and returns the default unresolved runtime classpath and modulepath for the given project.
	 *
	 * @param project
	 *            the {@link IJavaProject} to compute the unresolved runtime classpath and modulepath for
	 * @return runtime classpath and modulepath entries
	 * @exception CoreException
	 *                if unable to compute the runtime classpath and/or modulepath
	 * @see IRuntimeClasspathEntry
	 * @since 3.10
	 */
	public static IRuntimeClasspathEntry[] computeUnresolvedRuntimeDependencies(IJavaProject project) throws CoreException {
		List<IRuntimeClasspathEntry> classpathEntries = new ArrayList<>(3);
		if (!(project instanceof JavaProject)) {
			return classpathEntries.toArray(new IRuntimeClasspathEntry[classpathEntries.size()]);
		}
		JavaProject javaProject = (JavaProject) project;
		IClasspathEntry[] entries = javaProject.getExpandedClasspath();

		IClasspathEntry entry1 = JavaCore.newProjectEntry(project.getProject().getFullPath());
		if (isModularProject(project)) {
			classpathEntries.add(new RuntimeClasspathEntry(entry1, IRuntimeClasspathEntry.MODULE_PATH));
		} else {
			classpathEntries.add(new RuntimeClasspathEntry(entry1, IRuntimeClasspathEntry.CLASS_PATH));
		}
		for (int i = 0; i < entries.length; i++) {
			IClasspathEntry entry = entries[i];
			switch (entry.getEntryKind()) {
				case IClasspathEntry.CPE_CONTAINER:
					IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
					if (container != null) {
						switch (container.getKind()) {
							case IClasspathContainer.K_APPLICATION:
								// don't look at application entries
								break;
							case IClasspathContainer.K_DEFAULT_SYSTEM:
								if (isModule(entry, project)) {
									classpathEntries.add(newRuntimeContainerClasspathEntry(container.getPath(), IRuntimeClasspathEntry.MODULE_PATH, project));
								} else {
									classpathEntries.add(newRuntimeContainerClasspathEntry(container.getPath(), IRuntimeClasspathEntry.CLASS_PATH, project));
								}
								break;
							case IClasspathContainer.K_SYSTEM:
								if (isModule(entry, project)) {
									classpathEntries.add(newRuntimeContainerClasspathEntry(container.getPath(), IRuntimeClasspathEntry.MODULE_PATH, project));
								} else {
									classpathEntries.add(newRuntimeContainerClasspathEntry(container.getPath(), IRuntimeClasspathEntry.CLASS_PATH, project));
								}
								break;
						}
					}
					break;
				case IClasspathEntry.CPE_PROJECT:
					String name = entry.getPath().lastSegment();
					IProject dep = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
					IJavaProject javaProject1 = JavaCore.create(dep);
					if (isModule(entry, project)) {
						classpathEntries.add(newProjectRuntimeClasspathEntry(javaProject1, IRuntimeClasspathEntry.MODULE_PATH));
					} else {
						classpathEntries.add(newProjectRuntimeClasspathEntry(javaProject1, IRuntimeClasspathEntry.CLASS_PATH));
					}
					break;
				case IClasspathEntry.CPE_VARIABLE:
					if (JRELIB_VARIABLE.equals(entry.getPath().segment(0))) {
						IRuntimeClasspathEntry jre = newVariableRuntimeClasspathEntry(entry.getPath());
						jre.setClasspathProperty(IRuntimeClasspathEntry.MODULE_PATH);
						classpathEntries.add(jre);
					}
					break;
				case IClasspathEntry.CPE_LIBRARY:
					IPackageFragmentRoot root = project.findPackageFragmentRoot(entry.getPath());
					if (root != null && !root.getRawClasspathEntry().getPath().segment(0).contains("JRE_CONTAINER")) { //$NON-NLS-1$
						IRuntimeClasspathEntry r;
						if (JavaRuntime.isModule(entry, project)) {
							r = JavaRuntime.newArchiveRuntimeClasspathEntry(entry.getPath(), IRuntimeClasspathEntry.MODULE_PATH);
						} else {
							r = JavaRuntime.newArchiveRuntimeClasspathEntry(entry.getPath(), IRuntimeClasspathEntry.CLASS_PATH);
						}
						r.setSourceAttachmentPath(entry.getSourceAttachmentPath());
						r.setSourceAttachmentRootPath(entry.getSourceAttachmentRootPath());
						classpathEntries.add(r);
					}
					break;
				default:
					break;
			}
		}

		IRuntimeClasspathEntry jreEntry = JavaRuntime.computeModularJREEntry(project);
		if (jreEntry != null) { // With some jre stub jars don't have jre entries
			classpathEntries.add(jreEntry);
		}
		return classpathEntries.toArray(new IRuntimeClasspathEntry[classpathEntries.size()]);
	}

	/**
	 * Checks if classpath entry is modular and project is modular .
	 *
	 * @param entry
	 *            the classpath entry
	 * @return boolean <code>true</code> if entry is module else <code>false</code>
	 * @since 3.10
	 */
	public static boolean isModule(IClasspathEntry entry, IJavaProject proj) {
		if (entry == null) {
			return false;
		}
		if (!isModularProject(proj)) {
			return false;
		}

		for (IClasspathAttribute classpathAttribute : entry.getExtraAttributes()) {
			if (classpathAttribute.getName().equals(IClasspathAttribute.MODULE) && "true".equals(classpathAttribute.getValue())) {//$NON-NLS-1$
				return true;
			}
		}
		return false;

	}

	/**
	 * Checks if configuration JRE is greater than 8.
	 *
	 * @param configuration
	 *            the launch configuration
	 * @return boolean <code>true</code> if jre used in configuration is greater than 8 else <code>false</code>
	 * @since 3.10
	 */
	public static boolean isModularConfiguration(ILaunchConfiguration configuration) {

		try {
			IVMInstall vm = JavaRuntime.computeVMInstall(configuration);
			return isModularJava(vm);
		}
		catch (CoreException e) {
			e.printStackTrace();
		}
		return false;

	}

	/**
	 * Checks if vm install is modular( version greater than 8).
	 *
	 * @param vm
	 *            the vm install
	 * @return boolean <code>true</code> if vm install is modular else <code>false</code>
	 * @since 3.10
	 */
	public static boolean isModularJava(IVMInstall vm) {

		if (vm instanceof AbstractVMInstall) {
			AbstractVMInstall install = (AbstractVMInstall) vm;
			String vmver = install.getJavaVersion();
			// versionToJdkLevel only handles 3 char versions = 1.5, 1.6, 1.7, etc
			if (vmver.length() > 3) {
				vmver = vmver.substring(0, 3);
			}
			if (JavaCore.compareJavaVersions(vmver, JavaCore.VERSION_1_8) > 0) {
				return true;
			}
		}
		return false;

	}

	/**
	 * Checks if project entry is modular
	 *
	 * @param proj
	 *            the project
	 * @return boolean <code>true</code> if project is modular else <code>false</code>
	 * @since 3.10
	 */
	public static boolean isModularProject(IJavaProject proj) {

		IModuleDescription module;
		try {
			module = proj == null ? null : proj.getModuleDescription();
			String modName = module == null ? null : module.getElementName();
			if (modName != null && modName.length() > 0) {
				return true;
			}
		}
		catch (JavaModelException e) {
		}
		return false;
	}

	/**
	 * Computes and returns the unresolved source lookup path for the given launch
	 * configuration.
	 *
	 * @param configuration launch configuration
	 * @return runtime classpath entries
	 * @exception CoreException if unable to compute the source lookup path
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry[] computeUnresolvedSourceLookupPath(ILaunchConfiguration configuration) throws CoreException {
		return getSourceLookupPathProvider(configuration).computeUnresolvedClasspath(configuration);
	}

	/**
	 * Resolves the given source lookup path, returning the resolved source lookup path
	 * in the context of the given launch configuration.
	 *
	 * @param entries unresolved entries
	 * @param configuration launch configuration
	 * @return resolved entries
	 * @exception CoreException if unable to resolve the source lookup path
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry[] resolveSourceLookupPath(IRuntimeClasspathEntry[] entries, ILaunchConfiguration configuration) throws CoreException {
		return getSourceLookupPathProvider(configuration).resolveClasspath(entries, configuration);
	}

	/**
	 * Returns the classpath provider for the given launch configuration.
	 *
	 * @param configuration launch configuration
	 * @return classpath provider
	 * @exception CoreException if unable to resolve the path provider
	 * @since 2.0
	 */
	public static IRuntimeClasspathProvider getClasspathProvider(ILaunchConfiguration configuration) throws CoreException {
		String providerId = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH_PROVIDER, (String)null);
		IRuntimeClasspathProvider provider = null;
		if (providerId == null) {
			provider = fgDefaultClasspathProvider;
		} else {
			provider = getClasspathProviders().get(providerId);
			if (provider == null) {
				abort(NLS.bind(LaunchingMessages.JavaRuntime_26, new String[]{providerId}), null);
			}
		}
		return provider;
	}

	/**
	 * Returns the source lookup path provider for the given launch configuration.
	 *
	 * @param configuration launch configuration
	 * @return source lookup path provider
	 * @exception CoreException if unable to resolve the path provider
	 * @since 2.0
	 */
	public static IRuntimeClasspathProvider getSourceLookupPathProvider(ILaunchConfiguration configuration) throws CoreException {
		String providerId = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH_PROVIDER, (String)null);
		IRuntimeClasspathProvider provider = null;
		if (providerId == null) {
			provider = fgDefaultSourcePathProvider;
		} else {
			provider = getClasspathProviders().get(providerId);
			if (provider == null) {
				abort(NLS.bind(LaunchingMessages.JavaRuntime_27, new String[]{providerId}), null);
			}
		}
		return provider;
	}

	/**
	 * Returns resolved entries for the given entry in the context of the given
	 * launch configuration. If the entry is of kind
	 * <code>VARIABLE</code> or <code>CONTAINER</code>, variable and container
	 * resolvers are consulted. If the entry is of kind <code>PROJECT</code>,
	 * and the associated Java project specifies non-default output locations,
	 * the corresponding output locations are returned. Otherwise, the given
	 * entry is returned.
	 * <p>
	 * If the given entry is a variable entry, and a resolver is not registered,
	 * the entry itself is returned. 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 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 IRuntimeClasspathEntryResolver
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, ILaunchConfiguration configuration) throws CoreException {
		switch (entry.getType()) {
			case IRuntimeClasspathEntry.PROJECT:
				// if the project has multiple output locations, they must be returned
				IResource resource = entry.getResource();
				if (resource instanceof IProject) {
					IProject p = (IProject)resource;
					IJavaProject project = JavaCore.create(p);
					if (project == null || !p.isOpen() || !project.exists()) {
						return new IRuntimeClasspathEntry[0];
					}
					IRuntimeClasspathEntry[] entries = resolveOutputLocations(project, entry.getClasspathProperty());
					if (entries != null) {
						return entries;
					}
				} else {
					if (isOptional(entry.getClasspathEntry())) {
						return new IRuntimeClasspathEntry[] {};
					}
					abort(NLS.bind(LaunchingMessages.JavaRuntime_Classpath_references_non_existant_project___0__3, new String[]{entry.getPath().lastSegment()}), null);
				}
				break;
			case IRuntimeClasspathEntry.VARIABLE:
				IRuntimeClasspathEntryResolver resolver = getVariableResolver(entry.getVariableName());
				if (resolver == null) {
					IRuntimeClasspathEntry[] resolved = resolveVariableEntry(entry, null, configuration);
					if (resolved != null) {
						return resolved;
					}
					break;
				}
				return resolver.resolveRuntimeClasspathEntry(entry, configuration);
			case IRuntimeClasspathEntry.CONTAINER:
				resolver = getContainerResolver(entry.getVariableName());
				if (resolver == null) {
					return computeDefaultContainerEntries(entry, configuration);
				}
				return resolver.resolveRuntimeClasspathEntry(entry, configuration);
			case IRuntimeClasspathEntry.ARCHIVE:
				// verify the archive exists
				String location = entry.getLocation();
				if (location != null) {
					File file = new File(location);
					if (file.exists()) {
						break;
					}
				}
				if (isOptional(entry.getClasspathEntry())) {
					return new IRuntimeClasspathEntry[] {};
				}
				abort(NLS.bind(LaunchingMessages.JavaRuntime_Classpath_references_non_existant_archive___0__4, new String[] { entry.getPath().toString() }), null);
			case IRuntimeClasspathEntry.OTHER:
				resolver = getContributedResolver(((IRuntimeClasspathEntry2)entry).getTypeId());
				return resolver.resolveRuntimeClasspathEntry(entry, configuration);
			default:
				break;
		}
		return new IRuntimeClasspathEntry[] {entry};
	}

	private static boolean isOptional(IClasspathEntry entry) {
		IClasspathAttribute[] extraAttributes = entry.getExtraAttributes();
		for (int i = 0, length = extraAttributes.length; i < length; i++) {
			IClasspathAttribute attribute = extraAttributes[i];
			if (IClasspathAttribute.OPTIONAL.equals(attribute.getName()) && Boolean.parseBoolean(attribute.getValue())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Default resolution for a classpath variable - resolve to an archive. Only
	 * one of project/configuration can be non-null.
	 *
	 * @param entry the {@link IRuntimeClasspathEntry} to try and resolve
	 * @param project the project context or <code>null</code>
	 * @param configuration configuration context or <code>null</code>
	 * @return IRuntimeClasspathEntry[]
	 * @throws CoreException if a problem is encountered trying to resolve the given classpath entry
	 */
	private static IRuntimeClasspathEntry[] resolveVariableEntry(IRuntimeClasspathEntry entry, IJavaProject project, ILaunchConfiguration configuration) throws CoreException {
		// default resolution - an archive
		IPath archPath = JavaCore.getClasspathVariable(entry.getVariableName());
		if (archPath != null) {
			if (entry.getPath().segmentCount() > 1) {
				archPath = archPath.append(entry.getPath().removeFirstSegments(1));
			}
			IPath srcPath = null;
			IPath srcVar = entry.getSourceAttachmentPath();
			IPath srcRootPath = null;
			IPath srcRootVar = entry.getSourceAttachmentRootPath();
			if (archPath != null && !archPath.isEmpty()) {
				if (srcVar != null && !srcVar.isEmpty()) {
					srcPath = JavaCore.getClasspathVariable(srcVar.segment(0));
					if (srcPath != null) {
						if (srcVar.segmentCount() > 1) {
							srcPath = srcPath.append(srcVar.removeFirstSegments(1));
						}
						if (srcRootVar != null && !srcRootVar.isEmpty()) {
							srcRootPath = JavaCore.getClasspathVariable(srcRootVar.segment(0));
							if (srcRootPath != null) {
								if (srcRootVar.segmentCount() > 1) {
									srcRootPath = srcRootPath.append(srcRootVar.removeFirstSegments(1));
								}
							}
						}
					}
				}
				// now resolve the archive (recursively)
				IClasspathEntry archEntry = JavaCore.newLibraryEntry(archPath, srcPath, srcRootPath, entry.getClasspathEntry().isExported());
				IRuntimeClasspathEntry runtimeArchEntry = newRuntimeClasspathEntry(archEntry);
				runtimeArchEntry.setClasspathProperty(entry.getClasspathProperty());
				if (configuration == null) {
					return resolveRuntimeClasspathEntry(runtimeArchEntry, project);
				}
				return resolveRuntimeClasspathEntry(runtimeArchEntry, configuration);
			}
		}
		return null;
	}

	/**
	 * Returns runtime classpath entries corresponding to the output locations
	 * of the given project, or null if the project only uses the default
	 * output location.
	 *
	 * @param project the {@link IJavaProject} to resolve the output locations for
	 * @param classpathProperty the type of classpath entries to create
	 * @return IRuntimeClasspathEntry[] or <code>null</code>
	 * @throws CoreException if output resolution encounters a problem
	 */
	private static IRuntimeClasspathEntry[] resolveOutputLocations(IJavaProject project, int classpathProperty) throws CoreException {
		List<IPath> nonDefault = new ArrayList<>();
		if (project.exists() && project.getProject().isOpen()) {
			IClasspathEntry entries[] = project.getRawClasspath();
			for (int i = 0; i < entries.length; i++) {
				IClasspathEntry classpathEntry = entries[i];
				if (classpathEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
					IPath path = classpathEntry.getOutputLocation();
					if (path != null) {
						nonDefault.add(path);
					}
				}
			}
		}
		if (nonDefault.isEmpty()) {
			return null;
		}
		// add the default location if not already included
		IPath def = project.getOutputLocation();
		if (!nonDefault.contains(def)) {
			nonDefault.add(def);
		}
		IRuntimeClasspathEntry[] locations = new IRuntimeClasspathEntry[nonDefault.size()];
		for (int i = 0; i < locations.length; i++) {
			IClasspathEntry newEntry = JavaCore.newLibraryEntry(nonDefault.get(i), null, null);
			locations[i] = new RuntimeClasspathEntry(newEntry);
			locations[i].setClasspathProperty(classpathProperty);
		}
		return locations;
	}

	/**
	 * Returns resolved entries for the given entry in the context of the given
	 * Java project. If the entry is of kind
	 * <code>VARIABLE</code> or <code>CONTAINER</code>, variable and container
	 * resolvers are consulted. If the entry is of kind <code>PROJECT</code>,
	 * and the associated Java project specifies non-default output locations,
	 * the corresponding output locations are returned. Otherwise, the given
	 * entry is returned.
	 * <p>
	 * If the given entry is a variable entry, and a resolver is not registered,
	 * the entry itself is returned. 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 Java project context
	 * @return resolved runtime classpath entry
	 * @exception CoreException if unable to resolve
	 * @see IRuntimeClasspathEntryResolver
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry[] resolveRuntimeClasspathEntry(IRuntimeClasspathEntry entry, IJavaProject project) throws CoreException {
		switch (entry.getType()) {
			case IRuntimeClasspathEntry.PROJECT:
				// if the project has multiple output locations, they must be returned
				IResource resource = entry.getResource();
				if (resource instanceof IProject) {
					IProject p = (IProject)resource;
					IJavaProject jp = JavaCore.create(p);
					if (jp != null && p.isOpen() && jp.exists()) {
						IRuntimeClasspathEntry[] entries = resolveOutputLocations(jp, entry.getClasspathProperty());
						if (entries != null) {
							return entries;
						}
					} else {
						return new IRuntimeClasspathEntry[0];
					}
				}
				break;
			case IRuntimeClasspathEntry.VARIABLE:
				IRuntimeClasspathEntryResolver resolver = getVariableResolver(entry.getVariableName());
				if (resolver == null) {
					IRuntimeClasspathEntry[] resolved = resolveVariableEntry(entry, project, null);
					if (resolved != null) {
						return resolved;
					}
					break;
				}
				return resolver.resolveRuntimeClasspathEntry(entry, project);
			case IRuntimeClasspathEntry.CONTAINER:
				resolver = getContainerResolver(entry.getVariableName());
				if (resolver == null) {
					return computeDefaultContainerEntries(entry, project);
				}
				return resolver.resolveRuntimeClasspathEntry(entry, project);
			case IRuntimeClasspathEntry.OTHER:
				resolver = getContributedResolver(((IRuntimeClasspathEntry2)entry).getTypeId());
				return resolver.resolveRuntimeClasspathEntry(entry, project);
			default:
				break;
		}
		return new IRuntimeClasspathEntry[] {entry};
	}

	/**
	 * Performs default resolution for a container entry.
	 * Delegates to the Java model.
	 * @param entry the {@link IRuntimeClasspathEntry} to compute default container entries for
	 * @param config the backing {@link ILaunchConfiguration}
	 * @return the complete listing of default container entries or an empty list, never <code>null</code>
	 * @throws CoreException if the computation encounters a problem
	 */
	private static IRuntimeClasspathEntry[] computeDefaultContainerEntries(IRuntimeClasspathEntry entry, ILaunchConfiguration config) throws CoreException {
		IJavaProject project = entry.getJavaProject();
		if (project == null) {
			project = getJavaProject(config);
		}
		return computeDefaultContainerEntries(entry, project);
	}

	/**
	 * Performs default resolution for a container entry.
	 * Delegates to the Java model.
	 * @param entry the {@link IRuntimeClasspathEntry} to compute default container entries for
	 * @param project the backing {@link IJavaProject}
	 * @return the complete listing of default container entries or an empty list, never <code>null</code>
	 * @throws CoreException if the computation encounters a problem
	 */
	private static IRuntimeClasspathEntry[] computeDefaultContainerEntries(IRuntimeClasspathEntry entry, IJavaProject project) throws CoreException {
		if (project == null || entry == null) {
			// cannot resolve without entry or project context
			return new IRuntimeClasspathEntry[0];
		}
		IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
		if (container == null) {
			abort(NLS.bind(LaunchingMessages.JavaRuntime_Could_not_resolve_classpath_container___0__1, new String[]{entry.getPath().toString()}), null);
			// execution will not reach here - exception will be thrown
			return null;
		}
		IClasspathEntry[] cpes = container.getClasspathEntries();
		int property = -1;
		switch (container.getKind()) {
			case IClasspathContainer.K_APPLICATION:
				property = IRuntimeClasspathEntry.USER_CLASSES;
				break;
			case IClasspathContainer.K_DEFAULT_SYSTEM:
				property = IRuntimeClasspathEntry.STANDARD_CLASSES;
				break;
			case IClasspathContainer.K_SYSTEM:
				property = IRuntimeClasspathEntry.BOOTSTRAP_CLASSES;
				break;
		}
		List<IRuntimeClasspathEntry> resolved = new ArrayList<>(cpes.length);
		List<IJavaProject> projects = fgProjects.get();
		Integer count = fgEntryCount.get();
		if (projects == null) {
			projects = new ArrayList<>();
			fgProjects.set(projects);
			count = new Integer(0);
		}
		int intCount = count.intValue();
		intCount++;
		fgEntryCount.set(new Integer(intCount));
		try {
			for (int i = 0; i < cpes.length; i++) {
				IClasspathEntry cpe = cpes[i];
				if (cpe.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
					IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(cpe.getPath().segment(0));
					IJavaProject jp = JavaCore.create(p);
					if (!projects.contains(jp)) {
						projects.add(jp);
						IRuntimeClasspathEntry classpath = newDefaultProjectClasspathEntry(jp);
						IRuntimeClasspathEntry[] entries = resolveRuntimeClasspathEntry(classpath, jp);
						for (int j = 0; j < entries.length; j++) {
							IRuntimeClasspathEntry e = entries[j];
							if (!resolved.contains(e)) {
								resolved.add(entries[j]);
							}
						}
					}
				} else {
					IRuntimeClasspathEntry e = newRuntimeClasspathEntry(cpe);
					if (!resolved.contains(e)) {
						resolved.add(e);
					}
				}
			}
		} finally {
			intCount--;
			if (intCount == 0) {
				fgProjects.set(null);
				fgEntryCount.set(null);
			} else {
				fgEntryCount.set(new Integer(intCount));
			}
		}
		// set classpath property
		IRuntimeClasspathEntry[] result = new IRuntimeClasspathEntry[resolved.size()];
		for (int i = 0; i < result.length; i++) {
			result[i] = resolved.get(i);
			result[i].setClasspathProperty(property);
		}
		return result;
	}

	/**
	 * Computes and returns the unresolved class path for the given launch configuration.
	 * Variable and container entries are unresolved.
	 *
	 * @param configuration launch configuration
	 * @return unresolved runtime classpath entries
	 * @exception CoreException if unable to compute the classpath
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry[] computeUnresolvedRuntimeClasspath(ILaunchConfiguration configuration) throws CoreException {
		return getClasspathProvider(configuration).computeUnresolvedClasspath(configuration);
	}

	/**
	 * Resolves the given classpath, returning the resolved classpath
	 * in the context of the given launch configuration.
	 *
	 * @param entries unresolved classpath
	 * @param configuration launch configuration
	 * @return resolved runtime classpath entries
	 * @exception CoreException if unable to compute the classpath
	 * @since 2.0
	 */
	public static IRuntimeClasspathEntry[] resolveRuntimeClasspath(IRuntimeClasspathEntry[] entries, ILaunchConfiguration configuration) throws CoreException {
		if (isModularConfiguration(configuration)) {
			IRuntimeClasspathEntry[] entries1 = getClasspathProvider(configuration).resolveClasspath(entries, configuration);
			ArrayList<IRuntimeClasspathEntry> entries2 = new ArrayList<>(entries1.length);
			for (IRuntimeClasspathEntry entry : entries1) {
				switch (entry.getClasspathEntry().getEntryKind()) {
					case IClasspathEntry.CPE_LIBRARY:
						try {
							IJavaProject project = JavaRuntime.getJavaProject(configuration);
							if (project == null) {
								entries2.add(entry);
							} else {
								IPackageFragmentRoot root = project.findPackageFragmentRoot(entry.getPath());
								if (root == null) {
									entries2.add(entry);
								} else if (root != null && !root.getRawClasspathEntry().getPath().segment(0).contains("JRE_CONTAINER")) { //$NON-NLS-1$
									entries2.add(entry);
								}
							}
						}
						catch (CoreException ex) {
							// Not a java project
							entries2.add(entry);
						}
						break;
					default:
						entries2.add(entry);

				}
			}
			return entries2.toArray(new IRuntimeClasspathEntry[entries2.size()]);
		}
		return getClasspathProvider(configuration).resolveClasspath(entries, configuration);
	}

	/**
	 * Return the <code>IJavaProject</code> referenced in the specified configuration or
	 * <code>null</code> if none. This method looks for the existence of the {@link IJavaLaunchConfigurationConstants#ATTR_PROJECT_NAME}
	 * attribute in the given configuration.
	 *
	 * @param configuration the {@link ILaunchConfiguration} to try and compute the {@link IJavaProject} from
	 * @return the referenced {@link IJavaProject} or <code>null</code>
	 * @exception CoreException if the referenced Java project does not exist
	 * @since 2.0
	 */
	public static IJavaProject getJavaProject(ILaunchConfiguration configuration) throws CoreException {
		String projectName = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null);
		if ((projectName == null) || (projectName.trim().length() < 1)) {
			return null;
		}
		IJavaProject javaProject = getJavaModel().getJavaProject(projectName);
		if (javaProject != null && javaProject.getProject().exists() && !javaProject.getProject().isOpen()) {
			abort(NLS.bind(LaunchingMessages.JavaRuntime_28, new String[] {configuration.getName(), projectName}), IJavaLaunchConfigurationConstants.ERR_PROJECT_CLOSED, null);
		}
		if ((javaProject == null) || !javaProject.exists()) {
			abort(NLS.bind(LaunchingMessages.JavaRuntime_Launch_configuration__0__references_non_existing_project__1___1, new String[] {configuration.getName(), projectName}), IJavaLaunchConfigurationConstants.ERR_NOT_A_JAVA_PROJECT, null);
		}
		return javaProject;
	}

	/**
	 * Convenience method to get the java model.
	 * @return the {@link IJavaModel} made against the {@link IWorkspaceRoot}
	 */
	private static IJavaModel getJavaModel() {
		return JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
	}

	/**
	 * Returns the VM install for the given launch configuration.
	 * The VM install is determined in the following prioritized way:
	 * <ol>
	 * <li>The VM install is explicitly specified on the launch configuration
	 *  via the <code>ATTR_JRE_CONTAINER_PATH</code> attribute (since 3.2).</li>
	 * <li>The VM install is explicitly specified on the launch configuration
	 * 	via the <code>ATTR_VM_INSTALL_TYPE</code> and <code>ATTR_VM_INSTALL_ID</code>
	 *  attributes.</li>
	 * <li>If no explicit VM install is specified, the VM 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
	 * 	VM install, the workspace default VM install is returned.</li>
	 * </ol>
	 *
	 * @param configuration launch configuration
	 * @return VM install
	 * @exception CoreException if unable to compute a VM install
	 * @since 2.0
	 */
	public static IVMInstall computeVMInstall(ILaunchConfiguration configuration) throws CoreException {
		String jreAttr = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, (String)null);
		if (jreAttr == null) {
			@SuppressWarnings("deprecation")
			String type = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE, (String)null);
			if (type == null) {
				IJavaProject proj = getJavaProject(configuration);
				if (proj != null) {
					IVMInstall vm = getVMInstall(proj);
					if (vm != null) {
						return vm;
					}
				}
			} else {
				@SuppressWarnings("deprecation")
				String name = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME, (String)null);
				return resolveVM(type, name, configuration);
			}
		} else {
			IPath jrePath = Path.fromPortableString(jreAttr);
			IClasspathEntry entry = JavaCore.newContainerEntry(jrePath);
			IRuntimeClasspathEntryResolver2 resolver = getVariableResolver(jrePath.segment(0));
			if (resolver != null) {
				return resolver.resolveVMInstall(entry);
			}
			resolver = getContainerResolver(jrePath.segment(0));
			if (resolver != null) {
				return resolver.resolveVMInstall(entry);
			}
		}

		return getDefaultVMInstall();
	}
	/**
	 * Returns the VM of the given type with the specified name.
	 *
	 * @param type VM type identifier
	 * @param name VM name
	 * @param configuration the backing {@link ILaunchConfiguration}
	 * @return VM install
	 * @exception CoreException if unable to resolve
	 * @since 3.2
	 */
	private static IVMInstall resolveVM(String type, String name, ILaunchConfiguration configuration) throws CoreException {
		IVMInstallType vt = getVMInstallType(type);
		if (vt == null) {
			// error type does not exist
			abort(NLS.bind(LaunchingMessages.JavaRuntime_Specified_VM_install_type_does_not_exist___0__2, new String[] {type}), null);
		}
		IVMInstall vm = null;
		// look for a name
		if (name == null) {
			// error - type specified without a specific install (could be an old config that specified a VM ID)
			// log the error, but choose the default VM.
			LaunchingPlugin.log(new Status(IStatus.WARNING, LaunchingPlugin.getUniqueIdentifier(), IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_VM_INSTALL, NLS.bind("VM not fully specified in launch configuration {0} - missing VM name. Reverting to default VM.", new String[] {configuration.getName()}), null));  //$NON-NLS-1$
			return getDefaultVMInstall();
		}
		vm = vt.findVMInstallByName(name);
		if (vm == null) {
			// error - install not found
			abort(NLS.bind(LaunchingMessages.JavaRuntime_Specified_VM_install_not_found__type__0___name__1__2, new String[] {vt.getName(), name}), null);
		} else {
			return vm;
		}
		// won't reach here
		return null;
	}

	/**
	 * 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
	 * @throws CoreException a {@link CoreException} wrapper
	 */
	private static void abort(String message, Throwable exception) throws CoreException {
		abort(message, IJavaLaunchConfigurationConstants.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
	 * @throws CoreException a {@link CoreException} wrapper
	 */
	private static void abort(String message, int code, Throwable exception) throws CoreException {
		throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), code, message, exception));
	}

	/**
	 * Computes the default application classpath entries for the given
	 * project.
	 *
	 * @param	jproject The project to compute the classpath for
	 * @return	The computed classpath. May be empty, but not null.
	 * @throws	CoreException if unable to compute the default classpath
	 */
	public static String[] computeDefaultRuntimeClassPath(IJavaProject jproject) throws CoreException {
		IRuntimeClasspathEntry[] unresolved = computeUnresolvedRuntimeClasspath(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++) {
			IRuntimeClasspathEntry entry = unresolved[i];
			if (entry.getClasspathProperty() == IRuntimeClasspathEntry.USER_CLASSES) {
				IRuntimeClasspathEntry[] entries = resolveRuntimeClasspathEntry(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()]);
	}

	/**
	 * Saves the VM configuration information to the preferences. This includes
	 * the following information:
	 * <ul>
	 * <li>The list of all defined IVMInstall instances.</li>
	 * <li>The default VM</li>
	 * <ul>
	 * This state will be read again upon first access to VM
	 * configuration information.
	 * @throws CoreException if trying to save the current state of VMs encounters a problem
	 */
	public static void saveVMConfiguration() throws CoreException {
		if (fgVMTypes == null) {
			// if the VM types have not been instantiated, there can be no changes.
			return;
		}
		String xml = getVMsAsXML();
		InstanceScope.INSTANCE.getNode(LaunchingPlugin.ID_PLUGIN).put(PREF_VM_XML, xml);
		savePreferences();
	}

	/**
	 * Returns the listing of currently installed VMs as a single XML file
	 * @return an XML representation of all of the currently installed VMs
	 * @throws CoreException if trying to compute the XML for the VM state encounters a problem
	 */
	private static String getVMsAsXML() throws CoreException {
		VMDefinitionsContainer container = new VMDefinitionsContainer();
		container.setDefaultVMInstallCompositeID(getDefaultVMId());
		container.setDefaultVMInstallConnectorTypeID(getDefaultVMConnectorId());
		IVMInstallType[] vmTypes = getVMInstallTypes();
		IVMInstall[] vms = null;
		for (int i = 0; i < vmTypes.length; ++i) {
			vms = vmTypes[i].getVMInstalls();
			for (int j = 0; j < vms.length; j++) {
				container.addVM(vms[j]);
			}
		}
		return container.getAsXML();
	}

	/**
	 * This method loads installed JREs based an existing user preference
	 * or old VM configurations file. The VMs found in the preference
	 * or VM configurations file are added to the given VM definitions container.
	 *
	 * Returns whether the user preferences should be set - i.e. if it was
	 * not already set when initialized.
	 * @param vmDefs the container to add persisted VM information to
	 * @return whether the user preferences should be set
	 * @throws IOException if reading the {@link #PREF_VM_XML} preference stream encounters a problem
	 */
	private static boolean addPersistedVMs(VMDefinitionsContainer vmDefs) throws IOException {
		// Try retrieving the VM preferences from the preference store
		String vmXMLString = InstanceScope.INSTANCE.getNode(LaunchingPlugin.ID_PLUGIN).get(PREF_VM_XML, ""); //$NON-NLS-1$

		// If the preference was found, load VMs from it into memory
		if (vmXMLString.length() > 0) {
			try {
				ByteArrayInputStream inputStream = new ByteArrayInputStream(vmXMLString.getBytes("UTF8")); //$NON-NLS-1$
				VMDefinitionsContainer.parseXMLIntoContainer(inputStream, vmDefs);
				return false;
			} catch (IOException ioe) {
				LaunchingPlugin.log(ioe);
			}
		} else {
			// Otherwise, look for the old file that previously held the VM definitions
			IPath stateLocation= LaunchingPlugin.getDefault().getStateLocation();
			IPath stateFile= stateLocation.append("vmConfiguration.xml"); //$NON-NLS-1$
			File file = new File(stateFile.toOSString());

			if (file.exists()) {
				// If file exists, load VM definitions from it into memory and write the definitions to
				// the preference store WITHOUT triggering any processing of the new value
				InputStream fileInputStream = new BufferedInputStream(new FileInputStream(file));
				VMDefinitionsContainer.parseXMLIntoContainer(fileInputStream, vmDefs);
			}
		}
		return true;
	}

	/**
	 * Loads contributed VM installs
	 * @param vmDefs the container to add contributed VM install information to
	 * @since 3.2
	 */
	private static void addVMExtensions(VMDefinitionsContainer vmDefs) {
		IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(LaunchingPlugin.ID_PLUGIN, JavaRuntime.EXTENSION_POINT_VM_INSTALLS);
		IConfigurationElement[] configs= extensionPoint.getConfigurationElements();
		for (int i = 0; i < configs.length; i++) {
			IConfigurationElement element = configs[i];
			try {
				if ("vmInstall".equals(element.getName())) { //$NON-NLS-1$
					String vmType = element.getAttribute("vmInstallType"); //$NON-NLS-1$
					if (vmType == null) {
						abort(NLS.bind("Missing required vmInstallType attribute for vmInstall contributed by {0}", //$NON-NLS-1$
								new String[]{element.getContributor().getName()}), null);
					}
					String id = element.getAttribute("id"); //$NON-NLS-1$
					if (id == null) {
						abort(NLS.bind("Missing required id attribute for vmInstall contributed by {0}", //$NON-NLS-1$
								new String[]{element.getContributor().getName()}), null);
					}
					IVMInstallType installType = getVMInstallType(vmType);
					if (installType == null) {
						abort(NLS.bind("vmInstall {0} contributed by {1} references undefined VM install type {2}", //$NON-NLS-1$
								new String[]{id, element.getContributor().getName(), vmType}), null);
					}
					IVMInstall install = installType.findVMInstall(id);
					if (install == null) {
						// only load/create if first time we've seen this VM install
						String name = element.getAttribute("name"); //$NON-NLS-1$
						if (name == null) {
							abort(NLS.bind("vmInstall {0} contributed by {1} missing required attribute name", //$NON-NLS-1$
									new String[]{id, element.getContributor().getName()}), null);
						}
						String home = element.getAttribute("home"); //$NON-NLS-1$
						if (home == null) {
							abort(NLS.bind("vmInstall {0} contributed by {1} missing required attribute home", //$NON-NLS-1$
									new String[]{id, element.getContributor().getName()}), null);
						}
						String javadoc = element.getAttribute("javadocURL"); //$NON-NLS-1$
						String vmArgs = element.getAttribute("vmArgs"); //$NON-NLS-1$
						VMStandin standin = null;
						home = substitute(home);
						File homeDir = new File(home);
                        if (homeDir.exists()) {
                            try {
                            	// adjust for relative path names
                                home = homeDir.getCanonicalPath();
                                homeDir = new File(home);
                            } catch (IOException e) {
                            }
                        }
						if (EEVMType.ID_EE_VM_TYPE.equals(installType.getId())) {
							standin = createVMFromDefinitionFile(homeDir, name, id);
						} else {
							standin = new VMStandin(installType, id);
							standin.setName(name);
	                        IStatus status = installType.validateInstallLocation(homeDir);
	                        if (!status.isOK()) {
	                        	abort(NLS.bind("Illegal install location {0} for vmInstall {1} contributed by {2}: {3}", //$NON-NLS-1$
	                        			new String[]{home, id, element.getContributor().getName(), status.getMessage()}), null);
	                        }
	                        standin.setInstallLocation(homeDir);
							if (javadoc != null) {
								try {
									standin.setJavadocLocation(new URL(javadoc));
								} catch (MalformedURLException e) {
									abort(NLS.bind("Illegal javadocURL attribute for vmInstall {0} contributed by {1}", //$NON-NLS-1$
											new String[]{id, element.getContributor().getName()}), e);
								}
							}
							// allow default arguments to be specified by VM install type if no explicit arguments
							if (vmArgs == null) {
								if (installType instanceof AbstractVMInstallType) {
									AbstractVMInstallType type = (AbstractVMInstallType) installType;
									vmArgs = type.getDefaultVMArguments(homeDir);
								}
							}
							if (vmArgs != null) {
								standin.setVMArgs(vmArgs);
							}
	                        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(NLS.bind("library for vmInstall {0} contributed by {1} missing required attribute libPath", //$NON-NLS-1$
	                                            new String[]{id, element.getContributor().getName()}), null);
	                                }
	                                String sourcePathStr = library.getAttribute("sourcePath"); //$NON-NLS-1$
	                                String packageRootStr = library.getAttribute("packageRootPath"); //$NON-NLS-1$
	                                String javadocOverride = library.getAttribute("javadocURL"); //$NON-NLS-1$
	                                URL url = null;
	                                if (javadocOverride != null) {
	                                    try {
	                                        url = new URL(javadocOverride);
	                                    } catch (MalformedURLException e) {
	                                        abort(NLS.bind("Illegal javadocURL attribute specified for library {0} for vmInstall {1} contributed by {2}" //$NON-NLS-1$
	                                                ,new String[]{libPathStr, id, element.getContributor().getName()}), e);
	                                    }
	                                }
	                                IPath homePath = new Path(home);
	                                IPath libPath = homePath.append(substitute(libPathStr));
	                                IPath sourcePath = Path.EMPTY;
	                                if (sourcePathStr != null) {
	                                    sourcePath = homePath.append(substitute(sourcePathStr));
	                                }
	                                IPath packageRootPath = Path.EMPTY;
	                                if (packageRootStr != null) {
	                                    packageRootPath = new Path(substitute(packageRootStr));
	                                }
	                                locations[j] = new LibraryLocation(libPath, sourcePath, packageRootPath, url);
	                            }
	                        }
	                        standin.setLibraryLocations(locations);
						}
                        // in case the contributed JRE attributes changed, remove it first, then add
                        vmDefs.removeVM(standin);
                        vmDefs.addVM(standin);
					}
                    fgContributedVMs.add(id);
				} else {
					abort(NLS.bind("Illegal element {0} in vmInstalls extension contributed by {1}", //$NON-NLS-1$
							new String[]{element.getName(), element.getContributor().getName()}), null);
				}
			} catch (CoreException e) {
				LaunchingPlugin.log(e);
			}
		}
	}

    /**
     * Performs string substitution on the given expression.
     *
     * @param expression the expression to evaluate
     * @return expression after string substitution
     * @throws CoreException if the substitution encounters a problem
     * @since 3.2
     */
    private static String substitute(String expression) throws CoreException {
        return VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(expression);
    }

    /**
     * Returns whether the VM install with the specified id was contributed via
     * the vmInstalls extension point.
     *
     * @param id VM id
     * @return whether the VM install was contributed via extension point
     * @since 3.2
     */
    public static boolean isContributedVMInstall(String id) {
        getVMInstallTypes(); // ensure VMs are initialized
        return fgContributedVMs.contains(id);
    }

	/**
	 * Evaluates library locations for a IVMInstall. If no library locations are set on the install, a default
	 * location is evaluated and checked if it exists.
	 * @param vm the {@link IVMInstall} to compute locations for
	 * @return library locations with paths that exist or are empty
	 * @since 2.0
	 */
	public static LibraryLocation[] getLibraryLocations(IVMInstall vm)  {
		IPath[] libraryPaths;
		IPath[] sourcePaths;
		IPath[] sourceRootPaths;
		IPath[] annotationPaths;
		URL[] javadocLocations;
		URL[] indexes;
		LibraryLocation[] locations= vm.getLibraryLocations();
		if (locations == null) {
            URL defJavaDocLocation = vm.getJavadocLocation();
			File installLocation = vm.getInstallLocation();
			if (installLocation == null) {
				return new LibraryLocation[0];
			}
			LibraryLocation[] dflts= vm.getVMInstallType().getDefaultLibraryLocations(installLocation);
			libraryPaths = new IPath[dflts.length];
			sourcePaths = new IPath[dflts.length];
			sourceRootPaths = new IPath[dflts.length];
			javadocLocations= new URL[dflts.length];
			indexes = new URL[dflts.length];
			annotationPaths = new IPath[dflts.length];
			for (int i = 0; i < dflts.length; i++) {
				libraryPaths[i]= dflts[i].getSystemLibraryPath();
                if (defJavaDocLocation == null) {
                    javadocLocations[i]= dflts[i].getJavadocLocation();
                } else {
                    javadocLocations[i]= defJavaDocLocation;
                }
                indexes[i] = dflts[i].getIndexLocation();
				if (!libraryPaths[i].toFile().isFile()) {
					libraryPaths[i]= Path.EMPTY;
				}

				annotationPaths[i] = Path.EMPTY;

				sourcePaths[i]= dflts[i].getSystemLibrarySourcePath();
				if (sourcePaths[i].toFile().isFile()) {
					sourceRootPaths[i]= dflts[i].getPackageRootPath();
				} else {
					sourcePaths[i]= Path.EMPTY;
					sourceRootPaths[i]= Path.EMPTY;
				}
			}
		} else {
			libraryPaths = new IPath[locations.length];
			sourcePaths = new IPath[locations.length];
			sourceRootPaths = new IPath[locations.length];
			javadocLocations= new URL[locations.length];
			indexes = new URL[locations.length];
			annotationPaths = new IPath[locations.length];
			for (int i = 0; i < locations.length; i++) {
				libraryPaths[i]= locations[i].getSystemLibraryPath();
				sourcePaths[i]= locations[i].getSystemLibrarySourcePath();
				sourceRootPaths[i]= locations[i].getPackageRootPath();
				javadocLocations[i]= locations[i].getJavadocLocation();
				annotationPaths[i] = locations[i].getExternalAnnotationsPath();
				indexes[i] = locations[i].getIndexLocation();
			}
		}
		locations = new LibraryLocation[sourcePaths.length];
		for (int i = 0; i < sourcePaths.length; i++) {
			locations[i] = new LibraryLocation(libraryPaths[i], sourcePaths[i], sourceRootPaths[i], javadocLocations[i], indexes[i], annotationPaths[i]);
		}
		return locations;
	}

	/**
	 * Detect the VM that Eclipse is running on.
	 *
	 * @return a VM stand-in representing the VM that Eclipse is running on, or
	 * <code>null</code> if unable to detect the runtime VM
	 */
	private static VMStandin detectEclipseRuntime() {
		// Try to detect a VM for each declared VM type
		IVMInstallType[] vmTypes= getVMInstallTypes();
		// If we are running from an EE file, setup the VM from it
		for (int i = 0; i < vmTypes.length; i++) {
			if (vmTypes[i] instanceof EEVMType){
				String eeFileName = System.getProperty("ee.filename"); //$NON-NLS-1$
				if (eeFileName != null){
					File vmFile = new File(eeFileName);
					if (vmFile.isDirectory()){
						vmFile = new File(vmFile, "default.ee"); //$NON-NLS-1$
					}
					if (vmFile.isFile()){
						// Make sure the VM id is unique
						long unique = System.currentTimeMillis();
						while (vmTypes[i].findVMInstall(String.valueOf(unique)) != null) {
							unique++;
						}

						// Create a stand-in for the detected VM and add it to the result collector
						String vmID = String.valueOf(unique);
						try{
							return createVMFromDefinitionFile(vmFile, "", vmID); //$NON-NLS-1$
						} catch (CoreException e){
							// The file was not a valid EE file, continue the detection process
						}
					}
				}
			}
		}

		// Try to create a VM install using the install location
		for (int i = 0; i < vmTypes.length; i++) {
			File detectedLocation= vmTypes[i].detectInstallLocation();
			if (detectedLocation != null) {

				// Make sure the VM id is unique
				long unique = System.currentTimeMillis();
				IVMInstallType vmType = vmTypes[i];
				while (vmType.findVMInstall(String.valueOf(unique)) != null) {
					unique++;
				}

				// Create a stand-in for the detected VM and add it to the result collector
				String vmID = String.valueOf(unique);
				VMStandin detectedVMStandin = new VMStandin(vmType, vmID);
				detectedVMStandin.setInstallLocation(detectedLocation);
				detectedVMStandin.setName(generateDetectedVMName(detectedVMStandin));
				if (vmType instanceof AbstractVMInstallType) {
				    AbstractVMInstallType abs = (AbstractVMInstallType)vmType;
				    URL url = abs.getDefaultJavadocLocation(detectedLocation);
				    detectedVMStandin.setJavadocLocation(url);
				    String arguments = abs.getDefaultVMArguments(detectedLocation);
					if (arguments != null) {
						detectedVMStandin.setVMArgs(arguments);
					}
				}
				return detectedVMStandin;
			}
		}
		return null;
	}

	/**
	 * Returns whether the specified option is the same in the given
	 * map and preference store.
	 *
	 * <p>
	 * Notes:
	 * <ul>
	 * <li>Returns <code>false</code> if the option is only contained in one map</li>
	 * <li>Returns <code>true</code> if the option is not contained in either map</li>
	 * </ul>
	 * </p>
	 *
	 * @param optionName name of option to test
	 * @param options map of options
	 * @param prefStore preferences node
	 * @return whether the options are the same in both maps
	 */
	private static boolean equals(String optionName, Map<?, ?> options, org.osgi.service.prefs.Preferences prefStore) {
		String dummy= new String();
		String prefValue= prefStore.get(optionName, dummy);
		if (prefValue != null && prefValue != dummy) {
			return options.containsKey(optionName) &&
				equals(prefValue, options.get(optionName));
		}
		return !options.containsKey(optionName);
	}

	/**
	 * Returns whether the objects are equal or both <code>null</code>
	 *
	 * @param o1 an object
	 * @param o2 an object
	 * @return whether the objects are equal or both <code>null</code>
	 */
	private static boolean equals(Object o1, Object o2) {
		if (o1 == null) {
			return o2 == null;
		}
		return o1.equals(o2);
	}

	/**
	 * Make the name of a detected VM stand out.
	 * @param vm the VM to generate a name for
	 * @return the new name or <code>JRE</code>
	 */
	private static String generateDetectedVMName(IVMInstall vm) {
		String name = vm.getInstallLocation().getName();
		name = name.trim();
		if (name.length() == 0) {
			name = LaunchingMessages.JavaRuntime_25;
		}
		return name;
	}

	/**
	 * Creates and returns a classpath entry describing
	 * the JRE_LIB classpath variable.
	 *
	 * @return a new IClasspathEntry that describes the JRE_LIB classpath variable
	 */
	public static IClasspathEntry getJREVariableEntry() {
		return JavaCore.newVariableEntry(
			new Path(JRELIB_VARIABLE),
			new Path(JRESRC_VARIABLE),
			new Path(JRESRCROOT_VARIABLE)
		);
	}

	/**
	 * Creates and returns a classpath entry describing
	 * the default JRE container entry.
	 *
	 * @return a new IClasspathEntry that describes the default JRE container entry
	 * @since 2.0
	 */
	public static IClasspathEntry getDefaultJREContainerEntry() {
		return JavaCore.newContainerEntry(newDefaultJREContainerPath());
	}

	/**
	 * Returns a path for the JRE classpath container identifying the
	 * default VM install.
	 *
	 * @return classpath container path
	 * @since 3.2
	 */
	public static IPath newDefaultJREContainerPath() {
		return new Path(JRE_CONTAINER);
	}

	/**
	 * Returns a path for the JRE classpath container identifying the
	 * specified VM install by type and name.
	 *
	 * @param vm VM install
	 * @return classpath container path
	 * @since 3.2
	 */
	public static IPath newJREContainerPath(IVMInstall vm) {
		return newJREContainerPath(vm.getVMInstallType().getId(), vm.getName());
	}

	/**
	 * Returns a path for the JRE classpath container identifying the
	 * specified VM install by type and name.
	 *
	 * @param typeId VM install type identifier
	 * @param name VM install name
	 * @return classpath container path
	 * @since 3.2
	 */
	public static IPath newJREContainerPath(String typeId, String name) {
		IPath path = newDefaultJREContainerPath();
		path = path.append(typeId);
		path = path.append(name);
		return path;
	}

	/**
	 * Returns a path for the JRE classpath container identifying the
	 * specified execution environment.
	 *
	 * @param environment execution environment
	 * @return classpath container path
	 * @since 3.2
	 */
	public static IPath newJREContainerPath(IExecutionEnvironment environment) {
		IPath path = newDefaultJREContainerPath();
		path = path.append(StandardVMType.ID_STANDARD_VM_TYPE);
		path = path.append(JREContainerInitializer.encodeEnvironmentId(environment.getId()));
		return path;
	}

	/**
	 * Returns the JRE referenced by the specified JRE classpath container
	 * path or <code>null</code> if none.
	 *
	 * @param jreContainerPath the path to the container to try and resolve the {@link IVMInstall} from
	 * @return JRE referenced by the specified JRE classpath container
	 *  path or <code>null</code>
	 * @since 3.2
	 */
	public static IVMInstall getVMInstall(IPath jreContainerPath) {
		return JREContainerInitializer.resolveVM(jreContainerPath);
	}

	/**
	 * Returns the identifier of the VM install type referenced by the
	 * given JRE classpath container path, or <code>null</code> if none.
	 *
	 * @param jreContainerPath the path to the container to try and resolve the {@link IVMInstallType} id from
	 * @return VM install type identifier or <code>null</code>
	 * @since 3.2
	 */
	public static String getVMInstallTypeId(IPath jreContainerPath) {
		if (JREContainerInitializer.isExecutionEnvironment(jreContainerPath)) {
			return null;
		}
		return JREContainerInitializer.getVMTypeId(jreContainerPath);
	}

	/**
	 * Returns the name of the VM install referenced by the
	 * given JRE classpath container path, or <code>null</code> if none.
	 *
	 * @param jreContainerPath the path to the container to try an resolve the {@link IVMInstall} name from
	 * @return VM name or <code>null</code>
	 * @since 3.2
	 */
	public static String getVMInstallName(IPath jreContainerPath) {
		if (JREContainerInitializer.isExecutionEnvironment(jreContainerPath)) {
			return null;
		}
		return JREContainerInitializer.getVMName(jreContainerPath);
	}

	/**
	 * Returns the execution environment identifier in the following JRE
	 * classpath container path, or <code>null</code> if none.
	 *
	 * @param jreContainerPath classpath container path
	 * @return execution environment identifier or <code>null</code>
	 * @since 3.2
	 */
	public static String getExecutionEnvironmentId(IPath jreContainerPath) {
		return JREContainerInitializer.getExecutionEnvironmentId(jreContainerPath);
	}

	/**
	 * Returns a runtime classpath entry identifying the JRE to use when launching the specified
	 * configuration or <code>null</code> if none is specified. The entry returned represents a
	 * either a classpath variable or classpath container that resolves to a JRE.
	 * <p>
	 * The entry is resolved as follows:
	 * <ol>
	 * <li>If the <code>ATTR_JRE_CONTAINER_PATH</code> is present, it is used to create
	 *  a classpath container referring to a JRE.</li>
	 * <li>Next, if the <code>ATTR_VM_INSTALL_TYPE</code> and <code>ATTR_VM_INSTALL_NAME</code>
	 * attributes are present, they are used to create a classpath container.</li>
	 * <li>When none of the above attributes are specified, a default entry is
	 * created which refers to the JRE referenced by the build path of the configuration's
	 * associated Java project. This could be a classpath variable or classpath container.</li>
	 * <li>When there is no Java project associated with a configuration, the workspace
	 * default JRE is used to create a container path.</li>
	 * </ol>
	 * </p>
	 * @param configuration the backing {@link ILaunchConfiguration}
	 * @return classpath container path identifying a JRE or <code>null</code>
	 * @exception org.eclipse.core.runtime.CoreException if an exception occurs retrieving
	 *  attributes from the specified launch configuration
	 * @since 3.2
	 */
	public static IRuntimeClasspathEntry computeJREEntry(ILaunchConfiguration configuration) throws CoreException {
		String jreAttr = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, (String)null);
		IPath containerPath = null;
		if (jreAttr == null) {
			@SuppressWarnings("deprecation")
			String type = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE, (String)null);
			if (type == null) {
				// default JRE for the launch configuration
				IJavaProject proj = getJavaProject(configuration);
				if (proj == null) {
					containerPath = newDefaultJREContainerPath();
				} else {
					if (isModularConfiguration(configuration)) {
						return computeModularJREEntry(proj);
					}
					return computeJREEntry(proj);
				}
			} else {
				@SuppressWarnings("deprecation")
				String name = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME, (String)null);
				if (name != null) {
					containerPath = newDefaultJREContainerPath().append(type).append(name);
				}
			}
		} else {
			containerPath = Path.fromPortableString(jreAttr);
		}
		if (containerPath != null) {
			if (isModularConfiguration(configuration)) {
				return newRuntimeContainerClasspathEntry(containerPath, IRuntimeClasspathEntry.MODULE_PATH);
			}
			return newRuntimeContainerClasspathEntry(containerPath, IRuntimeClasspathEntry.STANDARD_CLASSES);
		}
		return null;
	}

	/**
	 * Returns a runtime classpath entry identifying the JRE referenced by the specified
	 * project, or <code>null</code> if none. The entry returned represents a either a
	 * classpath variable or classpath container that resolves to a JRE.
	 *
	 * @param project Java project
	 * @return JRE runtime classpath entry or <code>null</code>
	 * @exception org.eclipse.core.runtime.CoreException if an exception occurs
	 * 	accessing the project's classpath
	 * @since 3.2
	 */
	public static IRuntimeClasspathEntry computeJREEntry(IJavaProject project) throws CoreException {
		IClasspathEntry[] rawClasspath = project.getRawClasspath();
		IRuntimeClasspathEntryResolver2 resolver = null;
		for (int i = 0; i < rawClasspath.length; i++) {
			IClasspathEntry entry = rawClasspath[i];
			switch (entry.getEntryKind()) {
				case IClasspathEntry.CPE_VARIABLE:
					resolver = getVariableResolver(entry.getPath().segment(0));
					if (resolver != null) {
						if (resolver.isVMInstallReference(entry)) {
							return newRuntimeClasspathEntry(entry);
						}
					}
					break;
				case IClasspathEntry.CPE_CONTAINER:
					resolver = getContainerResolver(entry.getPath().segment(0));
					if (resolver != null) {
						if (resolver.isVMInstallReference(entry)) {
							IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
							if (container != null) {
								switch (container.getKind()) {
									case IClasspathContainer.K_APPLICATION:
										break;
									case IClasspathContainer.K_DEFAULT_SYSTEM:
										return newRuntimeContainerClasspathEntry(entry.getPath(), IRuntimeClasspathEntry.STANDARD_CLASSES);
									case IClasspathContainer.K_SYSTEM:
										return newRuntimeContainerClasspathEntry(entry.getPath(), IRuntimeClasspathEntry.BOOTSTRAP_CLASSES);
								}
							}
						}
					}
					break;
			}

		}
		return null;
	}

	/**
	 * Returns a runtime classpath or modulepath entry identifying the JRE referenced by the specified project, or <code>null</code> if none. The
	 * entry returned represents a either a classpath variable or classpath container that resolves to a JRE.
	 *
	 * @param project
	 *            Java project
	 * @return JRE runtime classpath or modulepath entry or <code>null</code>
	 * @exception org.eclipse.core.runtime.CoreException
	 *                if an exception occurs accessing the project's classpath
	 * @since 3.10
	 */
	public static IRuntimeClasspathEntry computeModularJREEntry(IJavaProject project) throws CoreException {
		IClasspathEntry[] rawClasspath = project.getRawClasspath();
		IRuntimeClasspathEntryResolver2 resolver = null;
		for (int i = 0; i < rawClasspath.length; i++) {
			IClasspathEntry entry = rawClasspath[i];
			switch (entry.getEntryKind()) {
				case IClasspathEntry.CPE_VARIABLE:
					resolver = getVariableResolver(entry.getPath().segment(0));
					if (resolver != null) {
						if (resolver.isVMInstallReference(entry)) {
							if (isModularProject(project)) {
								return newRuntimeClasspathEntry(entry, IRuntimeClasspathEntry.MODULE_PATH);
							}
							return newRuntimeClasspathEntry(entry, IRuntimeClasspathEntry.CLASS_PATH);
						}
					}
					break;
				case IClasspathEntry.CPE_CONTAINER:
					resolver = getContainerResolver(entry.getPath().segment(0));
					if (resolver != null) {
						if (resolver.isVMInstallReference(entry)) {
							IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
							if (container != null) {
								switch (container.getKind()) {
									case IClasspathContainer.K_APPLICATION:
										break;
									case IClasspathContainer.K_DEFAULT_SYSTEM:
										if (isModularProject(project)) {
											return newRuntimeContainerClasspathEntry(entry.getPath(), IRuntimeClasspathEntry.MODULE_PATH);
										}
										return newRuntimeContainerClasspathEntry(entry.getPath(), IRuntimeClasspathEntry.CLASS_PATH);
									case IClasspathContainer.K_SYSTEM:
										if (isModularProject(project)) {
											return newRuntimeContainerClasspathEntry(entry.getPath(), IRuntimeClasspathEntry.MODULE_PATH);
										}
										return newRuntimeContainerClasspathEntry(entry.getPath(), IRuntimeClasspathEntry.CLASS_PATH);
								}
							}
						}
					}
					break;
			}

		}
		return null;
	}

	/**
	 * Returns whether the given runtime classpath entry refers to a VM install.
	 *
	 * @param entry the entry to check
	 * @return whether the given runtime classpath entry refers to a VM install
	 * @since 3.2
	 */
	public static boolean isVMInstallReference(IRuntimeClasspathEntry entry) {
		IClasspathEntry classpathEntry = entry.getClasspathEntry();
		if (classpathEntry != null) {
			switch (classpathEntry.getEntryKind()) {
				case IClasspathEntry.CPE_VARIABLE:
					IRuntimeClasspathEntryResolver2 resolver = getVariableResolver(classpathEntry.getPath().segment(0));
					if (resolver != null) {
						return resolver.isVMInstallReference(classpathEntry);
					}
					break;
				case IClasspathEntry.CPE_CONTAINER:
					resolver = getContainerResolver(classpathEntry.getPath().segment(0));
					if (resolver != null) {
						return resolver.isVMInstallReference(classpathEntry);
					}
					break;
				}
		}
		return false;
	}

	/**
	 * Returns the VM connector defined with the specified identifier,
	 * or <code>null</code> if none.
	 *
	 * @param id VM connector identifier
	 * @return VM connector or <code>null</code> if none
	 * @since 2.0
	 */
	public static IVMConnector getVMConnector(String id) {
		return LaunchingPlugin.getDefault().getVMConnector(id);
	}

	/**
	 * Returns all VM connector extensions.
	 *
	 * @return VM connectors
	 * @since 2.0
	 */
	public static IVMConnector[] getVMConnectors() {
		return LaunchingPlugin.getDefault().getVMConnectors();
	}

	/**
	 * Returns the preference store for the launching plug-in.
	 *
	 * @return the preference store for the launching plug-in
	 * @since 2.0
	 */
	@SuppressWarnings("deprecation")
	public static Preferences getPreferences() {
		return LaunchingPlugin.getDefault().getPluginPreferences();
	}

	/**
	 * Saves the preferences for the launching plug-in.
	 *
	 * @since 2.0
	 */
	public static void savePreferences() {
		IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(LaunchingPlugin.ID_PLUGIN);
		try {
			prefs.flush();
		} catch (BackingStoreException e) {
			LaunchingPlugin.log(e);
		}
	}

	/**
	 * Registers the given resolver for the specified variable.
	 *
	 * @param resolver runtime classpath entry resolver
	 * @param variableName variable name to register for
	 * @since 2.0
	 */
	public static void addVariableResolver(IRuntimeClasspathEntryResolver resolver, String variableName) {
		Map<String, IRuntimeClasspathEntryResolver> map = getVariableResolvers();
		map.put(variableName, resolver);
	}

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

	/**
	 * Returns all registered variable resolvers.
	 * @return the initialized map of {@link RuntimeClasspathEntryResolver}s for variables
	 */
	private static Map<String, IRuntimeClasspathEntryResolver> getVariableResolvers() {
		if (fgVariableResolvers == null) {
			initializeResolvers();
		}
		return fgVariableResolvers;
	}

	/**
	 * Returns all registered container resolvers.
	 * @return the initialized map of {@link RuntimeClasspathEntryResolver}s for containers
	 */
	private static Map<String, IRuntimeClasspathEntryResolver> getContainerResolvers() {
		if (fgContainerResolvers == null) {
			initializeResolvers();
		}
		return fgContainerResolvers;
	}

	/**
	 * Returns all registered runtime classpath entry resolvers.
	 * @return the initialized map of {@link RuntimeClasspathEntryResolver}s for classpath entries
	 */
	private static Map<String, RuntimeClasspathEntryResolver> getEntryResolvers() {
		if (fgRuntimeClasspathEntryResolvers == null) {
			initializeResolvers();
		}
		return fgRuntimeClasspathEntryResolvers;
	}

	/**
	 * Initializes the listing of runtime classpath entry resolvers
	 */
	private static void initializeResolvers() {
		IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(LaunchingPlugin.ID_PLUGIN, EXTENSION_POINT_RUNTIME_CLASSPATH_ENTRY_RESOLVERS);
		IConfigurationElement[] extensions = point.getConfigurationElements();
		fgVariableResolvers = new HashMap<>(extensions.length);
		fgContainerResolvers = new HashMap<>(extensions.length);
		fgRuntimeClasspathEntryResolvers = new HashMap<>(extensions.length);
		for (int i = 0; i < extensions.length; i++) {
			RuntimeClasspathEntryResolver res = new RuntimeClasspathEntryResolver(extensions[i]);
			String variable = res.getVariableName();
			String container = res.getContainerId();
			String entryId = res.getRuntimeClasspathEntryId();
			if (variable != null) {
				fgVariableResolvers.put(variable, res);
			}
			if (container != null) {
				fgContainerResolvers.put(container, res);
			}
			if (entryId != null) {
				fgRuntimeClasspathEntryResolvers.put(entryId, res);
			}
		}
	}

	/**
	 * Returns all registered classpath providers.
	 * @return the initialized map of {@link RuntimeClasspathProvider}s
	 */
	private static Map<String, RuntimeClasspathProvider> getClasspathProviders() {
		if (fgPathProviders == null) {
			initializeProviders();
		}
		return fgPathProviders;
	}

	/**
	 * Initializes the listing of classpath providers
	 */
	private static void initializeProviders() {
		IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(LaunchingPlugin.ID_PLUGIN, EXTENSION_POINT_RUNTIME_CLASSPATH_PROVIDERS);
		IConfigurationElement[] extensions = point.getConfigurationElements();
		fgPathProviders = new HashMap<>(extensions.length);
		for (int i = 0; i < extensions.length; i++) {
			RuntimeClasspathProvider res = new RuntimeClasspathProvider(extensions[i]);
			fgPathProviders.put(res.getIdentifier(), res);
		}
	}

	/**
	 * Returns the resolver registered for the given variable, or
	 * <code>null</code> if none.
	 *
	 * @param variableName the variable to determine the resolver for
	 * @return the resolver registered for the given variable, or
	 * <code>null</code> if none
	 */
	private static IRuntimeClasspathEntryResolver2 getVariableResolver(String variableName) {
		return (IRuntimeClasspathEntryResolver2)getVariableResolvers().get(variableName);
	}

	/**
	 * 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 IRuntimeClasspathEntryResolver2 getContainerResolver(String containerId) {
		return (IRuntimeClasspathEntryResolver2)getContainerResolvers().get(containerId);
	}

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

	/**
	 * Adds the given listener to the list of registered VM install changed
	 * listeners. Has no effect if an identical listener is already registered.
	 *
	 * @param listener the listener to add
	 * @since 2.0
	 */
	public static void addVMInstallChangedListener(IVMInstallChangedListener listener) {
		fgVMListeners.add(listener);
	}

	/**
	 * Removes the given listener from the list of registered VM install changed
	 * listeners. Has no effect if an identical listener is not already registered.
	 *
	 * @param listener the listener to remove
	 * @since 2.0
	 */
	public static void removeVMInstallChangedListener(IVMInstallChangedListener listener) {
		fgVMListeners.remove(listener);
	}

	/**
	 * Notifies registered listeners that the default VM has changed
	 * @param previous the previous VM
	 * @param current the new current default VM
	 */
	private static void notifyDefaultVMChanged(IVMInstall previous, IVMInstall current) {
		for (IVMInstallChangedListener listener : fgVMListeners) {
			listener.defaultVMInstallChanged(previous, current);
		}
	}

	/**
	 * Notifies all VM install changed listeners of the given property change.
	 *
	 * @param event event describing the change.
	 * @since 2.0
	 */
	public static void fireVMChanged(PropertyChangeEvent event) {
		for (IVMInstallChangedListener listener : fgVMListeners) {
			listener.vmChanged(event);
		}
	}

	/**
	 * Notifies all VM install changed listeners of the VM addition
	 *
	 * @param vm the VM that has been added
	 * @since 2.0
	 */
	public static void fireVMAdded(IVMInstall vm) {
		if (!fgInitializingVMs) {
			for (IVMInstallChangedListener listener : fgVMListeners) {
				listener.vmAdded(vm);
			}
		}
	}

	/**
	 * Notifies all VM install changed listeners of the VM removal
	 *
	 * @param vm the VM that has been removed
	 * @since 2.0
	 */
	public static void fireVMRemoved(IVMInstall vm) {
		for (IVMInstallChangedListener listener : fgVMListeners) {
			listener.vmRemoved(vm);
		}
	}

	/**
	 * Return the String representation of the default output directory of the
	 * launch config's project or <code>null</code> if there is no configuration, no
	 * project or some sort of problem.
	 * @param config the {@link ILaunchConfiguration}
	 *
	 * @return the default output directory for the specified launch
	 * configuration's project
	 * @since 2.1
	 */
	public static String getProjectOutputDirectory(ILaunchConfiguration config) {
		try {
			if (config != null) {
				IJavaProject javaProject = JavaRuntime.getJavaProject(config);
				if (javaProject != null) {
					IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
					IPath outputLocation = javaProject.getOutputLocation();
					IResource resource = root.findMember(outputLocation);
					if (resource != null) {
						IPath path = resource.getFullPath();
						if (path != null)  {
							return path.makeRelative().toString();
						}
					}
				}
			}
		} catch (CoreException ce) {
		}
		return null;
	}

	/**
	 * Returns a collection of source containers corresponding to the given
	 * resolved runtime classpath entries.
	 * <p>
	 * Note that the entries must be resolved to ARCHIVE and PROJECT entries,
	 * as source containers cannot be determined for unresolved entries.
	 * </p>
	 * @param entries entries to translate
	 * @return source containers corresponding to the given runtime classpath entries
	 * @since 3.1
	 */
	public static ISourceContainer[] getSourceContainers(IRuntimeClasspathEntry[] entries) {
		return JavaSourceLookupUtil.translate(entries);
	}

	/**
	 * Returns a collection of paths that should be appended to the given project's
	 * <code>java.library.path</code> system property when launched. Entries are
	 * searched for on the project's build path as extra classpath 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 Java library path
	 * @since 3.1
	 * @see org.eclipse.jdt.core.IClasspathAttribute
	 * @see JavaRuntime#CLASSPATH_ATTR_LIBRARY_PATH_ENTRY
	 */
	public static String[] computeJavaLibraryPath(IJavaProject project, boolean requiredProjects) throws CoreException {
		Set<IJavaProject> visited = new HashSet<>();
		List<String> entries = new ArrayList<>();
		gatherJavaLibraryPathEntries(project, requiredProjects, visited, entries);
		List<String> resolved = new ArrayList<>(entries.size());
		Iterator<String> iterator = entries.iterator();
		IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		while (iterator.hasNext()) {
			String entry = iterator.next();
			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 Java 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 classpath entries
	 * @since 3.1
	 */
	private static void gatherJavaLibraryPathEntries(IJavaProject project, boolean requiredProjects, Set<IJavaProject> visited, List<String> entries) throws CoreException {
		if (visited.contains(project)) {
			return;
		}
		visited.add(project);
		IClasspathEntry[] rawClasspath = project.getRawClasspath();
		IClasspathEntry[] required = processJavaLibraryPathEntries(project, requiredProjects, rawClasspath, entries);
		if (required != null) {
			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
			for (int i = 0; i < required.length; i++) {
				IClasspathEntry entry = required[i];
				String projectName = entry.getPath().segment(0);
				IProject p = root.getProject(projectName);
				if (p.exists()) {
					IJavaProject requiredProject = JavaCore.create(p);
					if(requiredProject.isOpen()) {
						gatherJavaLibraryPathEntries(requiredProject, requiredProjects, visited, entries);
					}
					else if(!isOptional(entry)) {
						gatherJavaLibraryPathEntries(requiredProject, requiredProjects, visited, entries);
					}
				}
			}
		}
	}

	/**
	 * Adds all java library path extra classpath entry values to the given entries collection
	 * specified on the given project's classpath, and returns a collection of required
	 * projects, or <code>null</code>.
	 *
	 * @param project project being processed
	 * @param collectRequired whether to collect required projects
	 * @param classpathEntries the project's raw classpath
	 * @param entries collection to add java library path entries to
	 * @return required project classpath entries or <code>null</code>
	 * @throws CoreException if an exception occurs
	 * @since 3.1
	 */
	private static IClasspathEntry[] processJavaLibraryPathEntries(IJavaProject project, boolean collectRequired, IClasspathEntry[] classpathEntries, List<String> entries) throws CoreException {
		List<IClasspathEntry> req = null;
		for (int i = 0; i < classpathEntries.length; i++) {
			IClasspathEntry entry = classpathEntries[i];
			IClasspathAttribute[] 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() == IClasspathEntry.CPE_CONTAINER) {
				IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
				if (container != null) {
					IClasspathEntry[] requiredProjects = processJavaLibraryPathEntries(project, collectRequired, container.getClasspathEntries(), 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() == IClasspathEntry.CPE_PROJECT) {
				if (req == null) {
					req = new ArrayList<>();
				}
				req.add(entry);
			}
		}
		if (req != null) {
			return req.toArray(new IClasspathEntry[req.size()]);
		}
		return null;
	}

	/**
	 * Creates a new classpath 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 IClasspathEntry}.
	 * <p>
	 * The factory methods <code>newLibraryPathsAttribute(String[])</code>
	 * and <code>getLibraryPaths(IClasspathAttribute)</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 classpath attribute with the name <code>CLASSPATH_ATTR_LIBRARY_PATH_ENTRY</code>
	 * and an value encoded to the specified paths.
	 * @since 3.1
	 */
	public static IClasspathAttribute 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 JavaCore.newClasspathAttribute(CLASSPATH_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 IClasspathEntry}, 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(IClasspathAttribute)</code> should be used to
	 * encode and decode the attribute value.
	 * </p>
	 * @param attribute a <code>CLASSPATH_ATTR_LIBRARY_PATH_ENTRY</code> classpath 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 IClasspathEntry}, 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.
	 * @since 3.1
	 */
	public static String[] getLibraryPaths(IClasspathAttribute attribute) {
		if (CLASSPATH_ATTR_LIBRARY_PATH_ENTRY.equals(attribute.getName())) {
			String value = attribute.getValue();
			return value.split("\\|"); //$NON-NLS-1$
		}
		return null;
	}

	/**
	 * Returns the execution environments manager.
	 *
	 * @return execution environments manager
	 * @since 3.2
	 */
	public static IExecutionEnvironmentsManager getExecutionEnvironmentsManager() {
		return EnvironmentsManager.getDefault();
	}

	/**
	 * Perform VM type and VM install initialization. Does not hold locks
	 * while performing change notification.
	 *
	 * @since 3.2
	 */
	private static void initializeVMs() {
		VMDefinitionsContainer vmDefs = null;
		boolean setPref = false;
		boolean updateCompliance = false;
		synchronized (fgVMLock) {
			if (fgVMTypes == null) {
				try {
					fgInitializingVMs = true;
					// 1. load VM type extensions
					initializeVMTypeExtensions();
					try {
						vmDefs = new VMDefinitionsContainer();
						// 2. add persisted VMs
						setPref = addPersistedVMs(vmDefs);
						IStatus status = vmDefs.getStatus();
						if (status != null) {
							if (status.isMultiStatus()) {
								MultiStatus multi = (MultiStatus) status;
								IStatus[] children = multi.getChildren();
								for (int i = 0; i < children.length; i++) {
									IStatus child = children[i];
									if (!child.isOK()) {
										LaunchingPlugin.log(child);
									}
								}
							} else if (!status.isOK()) {
								LaunchingPlugin.log(status);
							}
						}

						// 3. if there are none, detect the eclipse runtime
						if (vmDefs.getValidVMList().isEmpty()) {
							// calling out to detectEclipseRuntime() could allow clients to change
							// VM settings (i.e. call back into change VM settings).
							VMListener listener = new VMListener();
							addVMInstallChangedListener(listener);
							setPref = true;
							VMStandin runtime = detectEclipseRuntime();
							removeVMInstallChangedListener(listener);
							if (!listener.isChanged()) {
								if (runtime != null) {
									updateCompliance = true;
									vmDefs.addVM(runtime);
									vmDefs.setDefaultVMInstallCompositeID(getCompositeIdFromVM(runtime));
								}
							} else {
								// VMs were changed - reflect current settings
								addPersistedVMs(vmDefs);
								vmDefs.setDefaultVMInstallCompositeID(fgDefaultVMId);
								updateCompliance = fgDefaultVMId != null;
							}
						}
						// 4. load contributed VM installs
						addVMExtensions(vmDefs);
						// 5. verify default VM is valid
						String defId = vmDefs.getDefaultVMInstallCompositeID();
						boolean validDef = false;
						if (defId != null) {
							Iterator<IVMInstall> iterator = vmDefs.getValidVMList().iterator();
							while (iterator.hasNext()) {
								IVMInstall vm = iterator.next();
								if (getCompositeIdFromVM(vm).equals(defId)) {
									validDef = true;
									break;
								}
							}
						}
						if (!validDef) {
							// use the first as the default
							setPref = true;
							List<IVMInstall> list = vmDefs.getValidVMList();
							if (!list.isEmpty()) {
								IVMInstall vm = list.get(0);
								vmDefs.setDefaultVMInstallCompositeID(getCompositeIdFromVM(vm));
							}
						}
						fgDefaultVMId = vmDefs.getDefaultVMInstallCompositeID();
						fgDefaultVMConnectorId = vmDefs.getDefaultVMInstallConnectorTypeID();

						// Create the underlying VMs for each valid VM
						List<IVMInstall> vmList = vmDefs.getValidVMList();
						Iterator<IVMInstall> vmListIterator = vmList.iterator();
						while (vmListIterator.hasNext()) {
							VMStandin vmStandin = (VMStandin) vmListIterator.next();
							vmStandin.convertToRealVM();
						}


					} catch (IOException e) {
						LaunchingPlugin.log(e);
					}
				} finally {
					fgInitializingVMs = false;
				}
			}
		}
		if (vmDefs != null) {
			// notify of initial VMs for backwards compatibility
			IVMInstallType[] installTypes = getVMInstallTypes();
			for (int i = 0; i < installTypes.length; i++) {
				IVMInstallType type = installTypes[i];
				IVMInstall[] installs = type.getVMInstalls();
				for (int j = 0; j < installs.length; j++) {
					fireVMAdded(installs[j]);
				}
			}

			// save settings if required
			if (setPref) {
				try {
					String xml = vmDefs.getAsXML();
					InstanceScope.INSTANCE.getNode(LaunchingPlugin.ID_PLUGIN).put(PREF_VM_XML, xml);
				}  catch (CoreException e) {
					LaunchingPlugin.log(e);
				}
			}
			// update compliance if required
			if (updateCompliance) {
				updateCompliance(getDefaultVMInstall());
			}
		}
	}

	/**
	 * Update compiler compliance settings based on the given VM.
	 *
	 * @param vm the backing {@link IVMInstall}
	 */
	private static void updateCompliance(IVMInstall vm) {
        if (vm instanceof IVMInstall2) {
            String javaVersion = ((IVMInstall2)vm).getJavaVersion();
            if (javaVersion != null) {
            	String compliance = null;
            	if (javaVersion.startsWith(JavaCore.VERSION_1_5)) {
            		compliance = JavaCore.VERSION_1_5;
            	} else if (javaVersion.startsWith(JavaCore.VERSION_1_6)) {
            		compliance = JavaCore.VERSION_1_6;
            	} else if (javaVersion.startsWith(JavaCore.VERSION_1_7)) {
            		compliance = JavaCore.VERSION_1_7;
				} else if (javaVersion.startsWith(JavaCore.VERSION_1_8)) {
					compliance = JavaCore.VERSION_1_8;
				} else if (javaVersion.startsWith(JavaCore.VERSION_9)
						&& (javaVersion.length() == JavaCore.VERSION_9.length() || javaVersion.charAt(JavaCore.VERSION_9.length()) == '.')) {
					compliance = JavaCore.VERSION_9;
				} else {
					compliance = JavaCore.VERSION_9; // use latest by default
				}

            	Hashtable<String, String> options= JavaCore.getOptions();

            	org.osgi.service.prefs.Preferences bundleDefaults = BundleDefaultsScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);

            	boolean isDefault =
            			equals(JavaCore.COMPILER_COMPLIANCE, options, bundleDefaults) &&
            			equals(JavaCore.COMPILER_SOURCE, options, bundleDefaults) &&
            			equals(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, options, bundleDefaults) &&
            			equals(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, options, bundleDefaults) &&
            			equals(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, options, bundleDefaults);
            	// only update the compliance settings if they are default settings, otherwise the
            	// settings have already been modified by a tool or user
            	if (isDefault) {
            		JavaCore.setComplianceOptions(compliance, options);
            		JavaCore.setOptions(options);
            	}

            }
        }
	}

	/**
	 * Creates a new VM based on the attributes specified in the given execution
	 * environment description file. The format of the file is defined by
	 * <code>http://wiki.eclipse.org/Execution_Environment_Descriptions</code>.
	 *
	 * @param eeFile VM definition file
	 * @param name name for the VM, or <code>null</code> if a default name should be assigned
	 * @param id id to assign to the new VM
	 * @return VM stand-in
	 * @exception CoreException if unable to create a VM from the given definition file
	 * @since 3.4
	 */
	public static VMStandin createVMFromDefinitionFile(File eeFile, String name, String id) throws CoreException {
		ExecutionEnvironmentDescription description = new ExecutionEnvironmentDescription(eeFile);
		IStatus status = EEVMType.validateDefinitionFile(description);
		if (status.isOK()) {
			VMStandin standin = new VMStandin(getVMInstallType(EEVMType.ID_EE_VM_TYPE), id);
			if (name != null && name.length() > 0){
				standin.setName(name);
			} else {
				name = description.getProperty(ExecutionEnvironmentDescription.EE_NAME);
				if (name == null) {
					name = eeFile.getName();
				}
				standin.setName(name);
			}
			String home = description.getProperty(ExecutionEnvironmentDescription.JAVA_HOME);
			standin.setInstallLocation(new File(home));
			standin.setLibraryLocations(description.getLibraryLocations());
			standin.setVMArgs(description.getVMArguments());
			standin.setJavadocLocation(EEVMType.getJavadocLocation(description.getProperties()));
			standin.setAttribute(EEVMInstall.ATTR_EXECUTION_ENVIRONMENT_ID, description.getProperty(ExecutionEnvironmentDescription.CLASS_LIB_LEVEL));
			File exe = description.getExecutable();
			if (exe == null) {
				exe = description.getConsoleExecutable();
			}
			if (exe != null) {
				try {
					standin.setAttribute(EEVMInstall.ATTR_JAVA_EXE, exe.getCanonicalPath());
				} catch (IOException e) {
					throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(),
							LaunchingMessages.JavaRuntime_24, e));
				}
			}
			standin.setAttribute(EEVMInstall.ATTR_JAVA_VERSION, description.getProperty(ExecutionEnvironmentDescription.LANGUAGE_LEVEL));
			standin.setAttribute(EEVMInstall.ATTR_DEFINITION_FILE, eeFile.getPath());
			standin.setAttribute(EEVMInstall.ATTR_DEBUG_ARGS, description.getProperty(ExecutionEnvironmentDescription.DEBUG_ARGS));
			return standin;
		}
		throw new CoreException(status);
	}
}
