bug 28945 (202 Branch)
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
index d2b4acb..a135c03 100644
--- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
+++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/JavaRuntime.java
@@ -1,1605 +1,1609 @@
-package org.eclipse.jdt.launching;
-
-/*******************************************************************************
- * Copyright (c) 2001, 2002 International Business Machines Corp. and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v0.5
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v05.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- ******************************************************************************/
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.xerces.dom.DocumentImpl;
-import org.eclipse.core.resources.IResource;
-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.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.debug.core.ILaunchConfiguration;
-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.JavaCore;
-import org.eclipse.jdt.internal.launching.CompositeId;
-import org.eclipse.jdt.internal.launching.JREContainerInitializer;
-import org.eclipse.jdt.internal.launching.JavaClasspathVariablesInitializer;
-import org.eclipse.jdt.internal.launching.JavaLaunchConfigurationUtils;
-import org.eclipse.jdt.internal.launching.LaunchingMessages;
-import org.eclipse.jdt.internal.launching.LaunchingPlugin;
-import org.eclipse.jdt.internal.launching.ListenerList;
-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.w3c.dom.Document;
-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 classpaths and source lookup paths for launch
- * configurations.
- * <p>
- * This class provides static methods only; it is not intended to be
- * instantiated or subclassed by clients.
- * </p>
- */
-public final class JavaRuntime {
-
- /**
- * Classpath variable name used for the default JRE's library.
- */
- public static final String JRELIB_VARIABLE= "JRE_LIB"; //$NON-NLS-1$
-
- /**
- * Classpath variable name used for the default JRE's library source.
- */
- public static final String JRESRC_VARIABLE= "JRE_SRC"; //$NON-NLS-1$
-
- /**
- * Classpath variable name used for the default JRE's library source root.
- */
- 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$
-
- /**
- * Classpath container used for a project's JRE. 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>
- *
- * @since 2.0
- */
- public static final String JRE_CONTAINER = LaunchingPlugin.getUniqueIdentifier() + ".JRE_CONTAINER"; //$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 millieseconds.
- *
- * @since 2.0
- */
- public static final String PREF_CONNECT_TIMEOUT = LaunchingPlugin.getUniqueIdentifier() + ".PREF_CONNECT_TIMEOUT"; //$NON-NLS-1$
-
- /**
- * Default launch/connect timeout (ms).
- *
- * @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.
- */
- public final static String ATTR_CMDLINE= LaunchingPlugin.getUniqueIdentifier() + ".launcher.cmdLine"; //$NON-NLS-1$
-
- private static IVMInstallType[] fgVMTypes= null;
- private static String fgDefaultVMId= null;
- private static String fgDefaultVMConnectorId = null;
-
- /**
- * Resolvers keyed by variable name and container id.
- */
- private static Map fgVariableResolvers = null;
- private static Map fgContainerResolvers = null;
-
- /**
- * Path providers keyed by id
- */
- private static Map 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 fgVMListeners = new ListenerList(5);
-
- /**
- * Not intended to be instantiated.
- */
- private JavaRuntime() {
- }
-
- /**
- * 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() {
- if (fgVMTypes == null) {
- initializeVMTypes();
- }
- return fgVMTypes;
- }
-
- private static synchronized void initializeVMTypes() {
- IExtensionPoint extensionPoint= Platform.getPluginRegistry().getExtensionPoint(LaunchingPlugin.getUniqueIdentifier() + ".vmInstallTypes"); //$NON-NLS-1$
- IConfigurationElement[] configs= extensionPoint.getConfigurationElements();
- MultiStatus status= new MultiStatus(LaunchingPlugin.getUniqueIdentifier(), IStatus.OK, LaunchingMessages.getString("JavaRuntime.exceptionOccurred"), null); //$NON-NLS-1$
- fgVMTypes= new IVMInstallType[configs.length];
-
- for (int i= 0; i < configs.length; i++) {
- try {
- IVMInstallType vmType= (IVMInstallType)configs[i].createExecutableExtension("class"); //$NON-NLS-1$
- fgVMTypes[i]= vmType;
- } catch (CoreException e) {
- status.add(e.getStatus());
- }
- }
- if (!status.isOK()) {
- //only happens on a CoreException
- LaunchingPlugin.log(status);
- //cleanup null entries in fgVMTypes
- List temp= new ArrayList(fgVMTypes.length);
- for (int i = 0; i < fgVMTypes.length; i++) {
- if(fgVMTypes[i] != null) {
- temp.add(fgVMTypes[i]);
- }
- fgVMTypes= new IVMInstallType[temp.size()];
- fgVMTypes= (IVMInstallType[])temp.toArray(fgVMTypes);
- }
- }
-
- try {
- initializeVMConfiguration();
- } catch (IOException e) {
- LaunchingPlugin.log(e);
- }
- }
-
- /**
- * 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.
- *
- * @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;
- for (int i = 0; i < classpath.length; i++) {
- IClasspathEntry 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;
- }
-
- private static IVMInstall getVMFromId(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 the VM install type with the given 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>
- */
- public static void setDefaultVMInstall(IVMInstall vm, IProgressMonitor monitor) throws CoreException {
- IVMInstall previous = null;
- if (fgDefaultVMId != null) {
- previous = getVMFromId(fgDefaultVMId);
- }
- fgDefaultVMId= getIdFromVM(vm);
- updateJREVariables(monitor);
- saveVMConfiguration();
- IVMInstall current = null;
- if (fgDefaultVMId != null) {
- current = getVMFromId(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 null to clear
- * the default.
- * @since 2.0
- */
- public static void setDefaultVMConnector(IVMConnector connector, IProgressMonitor monitor) throws CoreException {
- fgDefaultVMConnectorId= connector.getIdentifier();
- saveVMConfiguration();
- }
-
- private static void updateJREVariables(IProgressMonitor monitor) throws CoreException {
- JavaClasspathVariablesInitializer updater= new JavaClasspathVariablesInitializer();
- updater.updateJREVariables(monitor);
- JREContainerInitializer conatinerUpdater = new JREContainerInitializer();
- conatinerUpdater.updateDefaultJREContainers(monitor);
- }
- /**
- * 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= getVMFromId(getDefaultVMId());
- if (install != null && install.getInstallLocation().exists()) {
- return install;
- } else {
- // if the default JRE goes missing, re-detect
- if (install != null) {
- install.getVMInstallType().disposeVMInstall(install.getId());
- }
- fgDefaultVMId = null;
- try {
- //get rid of bad values on disk
- saveVMConfiguration();
- } catch(CoreException e) {
- LaunchingPlugin.log(e);
- }
- detectVMConfiguration();
- return getVMFromId(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;
- }
-
- private static String getDefaultVMId() {
- if (fgVMTypes == null) {
- initializeVMTypes();
- }
- return fgDefaultVMId;
- }
-
- private static String getDefaultVMConnectorId() {
- if (fgVMTypes == null) {
- initializeVMTypes();
- }
- return fgDefaultVMConnectorId;
- }
-
- private static String getIdFromVM(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();
- }
-
- /**
- * 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) {
- IClasspathEntry cpe = JavaCore.newProjectEntry(project.getProject().getFullPath());
- return newRuntimeClasspathEntry(cpe);
- }
-
-
- /**
- * 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) {
- IClasspathEntry cpe = JavaCore.newLibraryEntry(resource.getFullPath(), null, null);
- return newRuntimeClasspathEntry(cpe);
- }
-
- /**
- * 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) {
- IClasspathEntry cpe = JavaCore.newLibraryEntry(path, null, null);
- return newRuntimeClasspathEntry(cpe);
- }
-
- /**
- * 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) {
- IClasspathEntry cpe = JavaCore.newVariableEntry(path, null, null);
- return newRuntimeClasspathEntry(cpe);
- }
-
- /**
- * 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>, or <code>STANDARD_CLASSES</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 {
- IClasspathEntry cpe = JavaCore.newContainerEntry(path);
- return new RuntimeClasspathEntry(cpe, classpathProperty);
- }
-
- /**
- * Returns a runtime classpath entry constructed from the given memento.
- *
- * @param memento a menento 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 {
- return new RuntimeClasspathEntry(memento);
- }
-
- /**
- * 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);
- }
-
- /**
- * Computes and returns the default unresolved runtime claspath for the
- * given project.
- *
- * @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 entry = JavaCore.newProjectEntry(project.getProject().getFullPath());
- List classpathEntries = new ArrayList(5);
- expandProject(entry, classpathEntries);
- IRuntimeClasspathEntry[] runtimeEntries = new IRuntimeClasspathEntry[classpathEntries == null ? 0 : classpathEntries.size()];
- for (int i = 0; i < runtimeEntries.length; i++) {
- Object e = classpathEntries.get(i);
- if (e instanceof IClasspathEntry) {
- IClasspathEntry cpe = (IClasspathEntry)e;
- runtimeEntries[i] = newRuntimeClasspathEntry(cpe);
- } else {
- runtimeEntries[i] = (IRuntimeClasspathEntry)e;
- }
- }
- // sort bootpath and standard entries first
- IRuntimeClasspathEntry[] ordered = new IRuntimeClasspathEntry[runtimeEntries.length];
- int index = 0;
- for (int i = 0; i < runtimeEntries.length; i++) {
- if (runtimeEntries[i].getClasspathProperty() != IRuntimeClasspathEntry.USER_CLASSES) {
- ordered[index] = runtimeEntries[i];
- index++;
- runtimeEntries[i] = null;
- }
- }
- for (int i = 0; i < runtimeEntries.length; i++) {
- if (runtimeEntries[i] != null) {
- ordered[index] = runtimeEntries[i];
- index++;
- }
- }
- return ordered;
- }
-
- /**
- * 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 = (IRuntimeClasspathProvider)getClasspathProviders().get(providerId);
- }
- 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 = (IRuntimeClasspathProvider)getClasspathProviders().get(providerId);
- }
- 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>CONTAINTER</code>, variable and contanier
- * resolvers are consulted, otherwise, the returned entry is the same as the
- * given entry.
- * <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.VARIABLE:
- IRuntimeClasspathEntryResolver resolver = getVariableResolver(entry.getVariableName());
- if (resolver == null) {
- // no resolution by default
- break;
- } else {
- return resolver.resolveRuntimeClasspathEntry(entry, configuration);
- }
- case IRuntimeClasspathEntry.CONTAINER:
- resolver = getContainerResolver(entry.getVariableName());
- if (resolver == null) {
- return computeDefaultContainerEntries(entry, configuration);
- } else {
- return resolver.resolveRuntimeClasspathEntry(entry, configuration);
- }
- default:
- break;
- }
- return new IRuntimeClasspathEntry[] {entry};
- }
-
- /**
- * 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>CONTAINTER</code>, variable and contanier
- * resolvers are consulted, otherwise, the returned entry is the same as the given
- * entry.
- * <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.VARIABLE:
- IRuntimeClasspathEntryResolver resolver = getVariableResolver(entry.getVariableName());
- if (resolver == null) {
- // no resolution by default
- break;
- } else {
- return resolver.resolveRuntimeClasspathEntry(entry, project);
- }
- case IRuntimeClasspathEntry.CONTAINER:
- resolver = getContainerResolver(entry.getVariableName());
- if (resolver == null) {
- return computeDefaultContainerEntries(entry, project);
- } else {
- return resolver.resolveRuntimeClasspathEntry(entry, project);
- }
- default:
- break;
- }
- return new IRuntimeClasspathEntry[] {entry};
- }
-
- /**
- * Performs default resolution for a container entry.
- * Delegates to the Java model.
- */
- private static IRuntimeClasspathEntry[] computeDefaultContainerEntries(IRuntimeClasspathEntry entry, ILaunchConfiguration config) throws CoreException {
- return computeDefaultContainerEntries(entry, getJavaProject(config));
- }
-
- /**
- * Performs default resolution for a container entry.
- * Delegates to the Java model.
- */
- private static IRuntimeClasspathEntry[] computeDefaultContainerEntries(IRuntimeClasspathEntry entry, IJavaProject project) throws CoreException {
- if (project == null) {
- // cannot resolve without project context
- return new IRuntimeClasspathEntry[0];
- } else {
- IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
- 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;
- }
- IRuntimeClasspathEntry[] resolved = new IRuntimeClasspathEntry[cpes.length];
- for (int i = 0; i < resolved.length; i++) {
- resolved[i] = newRuntimeClasspathEntry(cpes[i]);
- resolved[i].setClasspathProperty(property);
- }
- return resolved;
- }
- }
-
- /**
- * 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 {
- return getClasspathProvider(configuration).resolveClasspath(entries, configuration);
- }
-
- /**
- * Return the <code>IJavaProject</code> referenced in the specified configuration or
- * <code>null</code> if none.
- *
- * @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.exists()) {
- abort(MessageFormat.format(LaunchingMessages.getString("JavaRuntime.Launch_configuration_{0}_references_non-existing_project_{1}._1"), new String[] {configuration.getName(), projectName}), IJavaLaunchConfigurationConstants.ERR_NOT_A_JAVA_PROJECT, null); //$NON-NLS-1$
- }
- return javaProject;
- }
-
- /**
- * Convenience method to get the java model.
- */
- private static IJavaModel getJavaModel() {
- return JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
- }
-
-
- /**
- * Returns a collection of runtime classpath entries that are defined in the
- * specified attribute of the given launch configuration.
- *
- * @param configuration launch configuration
- * @param attribute attribute name containing the list of entries
- * @return collection of runtime classpath entries that are defined in the
- * specified attribute of the given launch configuration
- * @exception CoreException if unable to retrieve the list
- */
- private static IRuntimeClasspathEntry[] recoverRuntimePath(ILaunchConfiguration configuration, String attribute) throws CoreException {
- List entries = (List)configuration.getAttribute(attribute, Collections.EMPTY_LIST);
- IRuntimeClasspathEntry[] rtes = new IRuntimeClasspathEntry[entries.size()];
- Iterator iter = entries.iterator();
- int i = 0;
- while (iter.hasNext()) {
- rtes[i] = newRuntimeClasspathEntry((String)iter.next());
- i++;
- }
- return rtes;
- }
-
- /**
- * 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_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 confiugration'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 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 {
- IVMInstallType vt = getVMInstallType(type);
- if (vt == null) {
- // error type does not exist
- abort(MessageFormat.format(LaunchingMessages.getString("JavaRuntime.Specified_VM_install_type_does_not_exist__{0}_2"), new String[] {type}), null); //$NON-NLS-1$
- }
- IVMInstall vm = null;
- // look for a name
- String name = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME, (String)null);
- 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.
- IStatus status = new Status(IStatus.WARNING, LaunchingPlugin.getUniqueIdentifier(), IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_VM_INSTALL, MessageFormat.format(LaunchingMessages.getString("JavaRuntime.VM_not_fully_specified_in_launch_configuration_{0}_-_missing_VM_name._Reverting_to_default_VM._1"), new String[] {configuration.getName()}), null); //$NON-NLS-1$
- LaunchingPlugin.log(status);
- return getDefaultVMInstall();
- } else {
- vm = vt.findVMInstallByName(name);
- if (vm == null) {
- // error - install not found
- abort(MessageFormat.format(LaunchingMessages.getString("JavaRuntime.Specified_VM_install_not_found__type_{0},_name_{1}_2"), new String[] {type, name}), null); //$NON-NLS-1$
- } else {
- return vm;
- }
- }
- }
-
- return getDefaultVMInstall();
- }
-
- /**
- * Throws a core exception with an internal error status.
- *
- * @param message the status message
- * @param exception lower level exception associated with the
- * error, or <code>null</code> if none
- */
- private static 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
- */
- private static void abort(String message, int code, Throwable exception) throws CoreException {
- throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), code, message, exception));
- }
-
- /**
- * Returns the transitive closure of classpath entries for the
- * given project entry.
- *
- * @param projectEntry project classpath entry
- * @param a list of entries already expanded, should be empty to begin,
- * and contains the result
- * @exception CoreException if unable to expand the classpath
- */
- private static void expandProject(IClasspathEntry projectEntry, List expandedPath) throws CoreException {
- // 1. Get the raw classpath
- // 2. Replace source folder entries with a project entry
- IPath projectPath = projectEntry.getPath();
- IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(projectPath.lastSegment());
- if (res == null) {
- return;
- }
- IJavaProject project = (IJavaProject)JavaCore.create(res);
- if (project == null) {
- return;
- }
- IClasspathEntry[] buildPath = project.getRawClasspath();
- List unexpandedPath = new ArrayList(buildPath.length);
- boolean projectAdded = false;
- for (int i = 0; i < buildPath.length; i++) {
- if (buildPath[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
- if (!projectAdded) {
- projectAdded = true;
- unexpandedPath.add(projectEntry);
- }
- } else {
- unexpandedPath.add(buildPath[i]);
- }
- }
- // 3. expand each project entry (except for the root project)
- // 4. replace each container entry with a runtime entry associated with the project
- Iterator iter = unexpandedPath.iterator();
- while (iter.hasNext()) {
- IClasspathEntry entry = (IClasspathEntry)iter.next();
- if (entry == projectEntry) {
- expandedPath.add(entry);
- } else {
- switch (entry.getEntryKind()) {
- case IClasspathEntry.CPE_PROJECT:
- if (!expandedPath.contains(entry)) {
- expandProject(entry, expandedPath);
- }
- break;
- case IClasspathEntry.CPE_CONTAINER:
- IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
- 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;
- }
- IRuntimeClasspathEntry r = newRuntimeContainerClasspathEntry(entry.getPath(), property);
- // check for duplicate/redundant entries
- boolean duplicate = false;
- for (int i = 0; i < expandedPath.size(); i++) {
- Object o = expandedPath.get(i);
- if (o instanceof IRuntimeClasspathEntry) {
- IRuntimeClasspathEntry re = (IRuntimeClasspathEntry)o;
- if (re.getType() == IRuntimeClasspathEntry.CONTAINER) {
- if (container instanceof IRuntimeContainerComparator) {
- duplicate = ((IRuntimeContainerComparator)container).isDuplicate(re.getPath());
- if (duplicate) {
- break;
- }
- } else if (re.getVariableName().equals(r.getVariableName())) {
- duplicate = true;
- break;
- }
- }
- }
- }
- if (!duplicate) {
- expandedPath.add(r);
- }
- break;
- case IClasspathEntry.CPE_VARIABLE:
- if (entry.getPath().segment(0).equals(JRELIB_VARIABLE)) {
- r = newVariableRuntimeClasspathEntry(entry.getPath());
- r.setSourceAttachmentPath(entry.getSourceAttachmentPath());
- r.setSourceAttachmentRootPath(entry.getSourceAttachmentRootPath());
- r.setClasspathProperty(IRuntimeClasspathEntry.STANDARD_CLASSES);
- if (!expandedPath.contains(r)) {
- expandedPath.add(r);
- }
- break;
- }
- // fall through if not the special JRELIB variable
- default:
- if (!expandedPath.contains(entry)) {
- expandedPath.add(entry);
- }
- break;
- }
- }
- }
- return;
- }
-
- /**
- * 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 resolved = new ArrayList(unresolved.length);
- for (int i = 0; i < unresolved.length; i++) {
- IRuntimeClasspathEntry entry = unresolved[i];
- if (unresolved[i].getClasspathProperty() == IRuntimeClasspathEntry.USER_CLASSES) {
- switch (entry.getType()) {
- case IRuntimeClasspathEntry.CONTAINER:
- IRuntimeClasspathEntry[] contained = computeDefaultContainerEntries(entry, jproject);
- for (int j = 0; j < contained.length; j++) {
- resolved.add(contained[j].getLocation());
- }
- break;
- default:
- resolved.add(entry.getLocation());
- break;
- }
- }
- }
- return (String[])resolved.toArray(new String[resolved.size()]);
- }
-
- /**
- * Saves the VM configuration information to disk. 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.
- */
- public static void saveVMConfiguration() throws CoreException {
- IPath stateLocation= LaunchingPlugin.getDefault().getStateLocation();
- IPath stateFile= stateLocation.append("vmConfiguration.xml"); //$NON-NLS-1$
- File f= new File(stateFile.toOSString());
- try {
- String xml = getVMsAsXML();
- FileOutputStream stream = new FileOutputStream(f);
- stream.write(xml.getBytes("UTF8")); //$NON-NLS-1$
- stream.close();
- } catch (IOException e) {
- throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), IStatus.ERROR, LaunchingMessages.getString("JavaRuntime.ioExceptionOccurred"), e)); //$NON-NLS-1$
- }
-
- }
-
- private static String getVMsAsXML() throws IOException {
- Document doc = new DocumentImpl();
- Element config = doc.createElement("vmSettings"); //$NON-NLS-1$
- if (fgDefaultVMId != null) {
- config.setAttribute("defaultVM", fgDefaultVMId); //$NON-NLS-1$
- }
- if (fgDefaultVMConnectorId != null) {
- config.setAttribute("defaultVMConnector", fgDefaultVMConnectorId); //$NON-NLS-1$
- }
- doc.appendChild(config);
-
- IVMInstallType[] vmTypes= getVMInstallTypes();
-
- for (int i = 0; i < vmTypes.length; ++i) {
- Element vmTypeElement = vmTypeAsElement(doc, vmTypes[i]);
- config.appendChild(vmTypeElement);
- }
-
- return JavaLaunchConfigurationUtils.serializeDocument(doc);
- }
-
- private static Element vmTypeAsElement(Document doc, IVMInstallType vmType) {
- Element element= doc.createElement("vmType"); //$NON-NLS-1$
- element.setAttribute("id", vmType.getId()); //$NON-NLS-1$
- IVMInstall[] vms= vmType.getVMInstalls();
- for (int i= 0; i < vms.length; i++) {
- Element vmElement= vmAsElement(doc, vms[i]);
- element.appendChild(vmElement);
- }
- return element;
- }
-
- private static Element vmAsElement(Document doc, IVMInstall vm) {
- Element element= doc.createElement("vm"); //$NON-NLS-1$
- element.setAttribute("id", vm.getId()); //$NON-NLS-1$
- element.setAttribute("name", vm.getName()); //$NON-NLS-1$
- String installPath= ""; //$NON-NLS-1$
- File installLocation= vm.getInstallLocation();
- if (installLocation != null) {
- installPath= installLocation.getAbsolutePath();
- }
- element.setAttribute("path", installPath); //$NON-NLS-1$
- LibraryLocation[] libraryLocations= vm.getLibraryLocations();
- if (libraryLocations != null) {
- Element libLocationElement= libraryLocationsAsElement(doc, libraryLocations);
- element.appendChild(libLocationElement);
- }
- return element;
- }
-
- private static Element libraryLocationsAsElement(Document doc, LibraryLocation[] locations) {
- Element root = doc.createElement("libraryLocations"); //$NON-NLS-1$
- for (int i = 0; i < locations.length; i++) {
- Element element= doc.createElement("libraryLocation"); //$NON-NLS-1$
- element.setAttribute("jreJar", locations[i].getSystemLibraryPath().toString()); //$NON-NLS-1$
- element.setAttribute("jreSrc", locations[i].getSystemLibrarySourcePath().toString()); //$NON-NLS-1$
- element.setAttribute("pkgRoot", locations[i].getPackageRootPath().toString()); //$NON-NLS-1$
- root.appendChild(element);
- }
- return root;
- }
-
- private static void initializeVMConfiguration() throws IOException {
- IPath stateLocation= LaunchingPlugin.getDefault().getStateLocation();
- IPath stateFile= stateLocation.append("vmConfiguration.xml"); //$NON-NLS-1$
- File f= new File(stateFile.toOSString());
- if (f.isFile()) {
- loadVMConfiguration(f);
- } else {
- detectVMConfiguration();
- }
- }
-
- private static void loadVMConfiguration(File f) throws IOException {
- InputStream stream= new BufferedInputStream(new FileInputStream(f));
- Reader reader= new InputStreamReader(stream, "UTF-8"); //$NON-NLS-1$
- Element config= null;
- try {
- DocumentBuilder parser= DocumentBuilderFactory.newInstance().newDocumentBuilder();
- config = parser.parse(new InputSource(reader)).getDocumentElement();
- } catch (SAXException e) {
- throw new IOException(LaunchingMessages.getString("JavaRuntime.badFormat")); //$NON-NLS-1$
- } catch (ParserConfigurationException e) {
- reader.close();
- throw new IOException(LaunchingMessages.getString("JavaRuntime.badFormat")); //$NON-NLS-1$
- } finally {
- reader.close();
- }
- if (!config.getNodeName().equalsIgnoreCase("vmSettings")) { //$NON-NLS-1$
- throw new IOException(LaunchingMessages.getString("JavaRuntime.badFormat")); //$NON-NLS-1$
- }
- fgDefaultVMId= config.getAttribute("defaultVM"); //$NON-NLS-1$
- fgDefaultVMConnectorId = config.getAttribute("defaultVMConnector"); //$NON-NLS-1$
- NodeList list = config.getChildNodes();
- int length = list.getLength();
- for (int i = 0; i < length; ++i) {
- Node node = list.item(i);
- short type = node.getNodeType();
- if (type == Node.ELEMENT_NODE) {
- Element vmTypeElement = (Element) node;
- if (vmTypeElement.getNodeName().equalsIgnoreCase("vmType")) { //$NON-NLS-1$
- createFromVMType(vmTypeElement);
- }
- }
- }
- }
-
- private static void detectVMConfiguration() {
- IVMInstallType[] vmTypes= getVMInstallTypes();
- boolean defaultSet= false;
- for (int i= 0; i < vmTypes.length; i++) {
- File detectedLocation= vmTypes[i].detectInstallLocation();
- if (detectedLocation != null) {
- int unique = i;
- IVMInstallType vmType = vmTypes[i];
- while (vmType.findVMInstall(String.valueOf(unique)) != null) {
- unique++;
- }
- IVMInstall detected= vmTypes[i].createVMInstall(String.valueOf(unique));
- detected.setName(LaunchingMessages.getString("JavaRuntime.detectedSuffix")); //$NON-NLS-1$
- detected.setInstallLocation(detectedLocation);
- if (detected != null && !defaultSet) {
- try {
- setDefaultVMInstall(detected, null);
- defaultSet= true;
- } catch (CoreException e) {
- LaunchingPlugin.log(e);
- }
- }
- }
- }
- }
-
- private static void createFromVMType(Element vmTypeElement) {
- String id = vmTypeElement.getAttribute("id"); //$NON-NLS-1$
- IVMInstallType vmType= getVMInstallType(id);
- if (vmType != null) {
- NodeList list = vmTypeElement.getChildNodes();
- int length = list.getLength();
- for (int i = 0; i < length; ++i) {
- Node node = list.item(i);
- short type = node.getNodeType();
- if (type == Node.ELEMENT_NODE) {
- Element vmElement = (Element) node;
- if (vmElement.getNodeName().equalsIgnoreCase("vm")) { //$NON-NLS-1$
- createVM(vmType, vmElement);
- }
- }
- }
- } else {
- LaunchingPlugin.log(LaunchingMessages.getString("JavaRuntime.VM_type_element_with_unknown_id_1")); //$NON-NLS-1$
- }
- }
-
- private static void createVM(IVMInstallType vmType, Element vmElement) {
- String id= vmElement.getAttribute("id"); //$NON-NLS-1$
- if (id != null) {
- String installPath= vmElement.getAttribute("path"); //$NON-NLS-1$
- if (installPath == null) {
- return;
- }
- File installLocation= new File(installPath);
- if (!installLocation.exists()) {
- return;
- }
- IVMInstall vm= vmType.createVMInstall(id);
- vm.setName(vmElement.getAttribute("name")); //$NON-NLS-1$
- vm.setInstallLocation(installLocation);
-
- NodeList list = vmElement.getChildNodes();
- int length = list.getLength();
- for (int i = 0; i < length; ++i) {
- Node node = list.item(i);
- short type = node.getNodeType();
- if (type == Node.ELEMENT_NODE) {
- Element libraryLocationElement= (Element)node;
- if (libraryLocationElement.getNodeName().equals("libraryLocation")) { //$NON-NLS-1$
- LibraryLocation loc = getLibraryLocation(vm, libraryLocationElement);
- vm.setLibraryLocations(new LibraryLocation[]{loc});
- break;
- } else if (libraryLocationElement.getNodeName().equals("libraryLocations")) { //$NON-NLS-1$
- setLibraryLocations(vm, libraryLocationElement);
- break;
- }
- }
- }
-
- } else {
- LaunchingPlugin.log(LaunchingMessages.getString("JavaRuntime.VM_element_specified_with_no_id_attribute_2")); //$NON-NLS-1$
- }
- }
-
- private static LibraryLocation getLibraryLocation(IVMInstall vm, Element libLocationElement) {
- String jreJar= libLocationElement.getAttribute("jreJar"); //$NON-NLS-1$
- String jreSrc= libLocationElement.getAttribute("jreSrc"); //$NON-NLS-1$
- String pkgRoot= libLocationElement.getAttribute("pkgRoot"); //$NON-NLS-1$
- if (jreJar != null && jreSrc != null && pkgRoot != null) {
- return new LibraryLocation(new Path(jreJar), new Path(jreSrc), new Path(pkgRoot));
- } else {
- LaunchingPlugin.log(LaunchingMessages.getString("JavaRuntime.Library_location_element_incorrectly_specified_3")); //$NON-NLS-1$
- }
- return null;
- }
-
- private static void setLibraryLocations(IVMInstall vm, Element libLocationsElement) {
- NodeList list = libLocationsElement.getChildNodes();
- int length = list.getLength();
- List locations = new ArrayList(length);
- for (int i = 0; i < length; ++i) {
- Node node = list.item(i);
- short type = node.getNodeType();
- if (type == Node.ELEMENT_NODE) {
- Element libraryLocationElement= (Element)node;
- if (libraryLocationElement.getNodeName().equals("libraryLocation")) { //$NON-NLS-1$
- locations.add(getLibraryLocation(vm, libraryLocationElement));
- }
- }
- }
- vm.setLibraryLocations((LibraryLocation[])locations.toArray(new LibraryLocation[locations.size()]));
- }
-
- /**
- * 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.
- * @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;
- LibraryLocation[] locations= vm.getLibraryLocations();
- if (locations == null) {
- LibraryLocation[] dflts= vm.getVMInstallType().getDefaultLibraryLocations(vm.getInstallLocation());
- libraryPaths = new IPath[dflts.length];
- sourcePaths = new IPath[dflts.length];
- sourceRootPaths = new IPath[dflts.length];
- for (int i = 0; i < dflts.length; i++) {
- libraryPaths[i]= dflts[i].getSystemLibraryPath();
- if (!libraryPaths[i].toFile().isFile()) {
- libraryPaths[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];
- for (int i = 0; i < locations.length; i++) {
- libraryPaths[i]= locations[i].getSystemLibraryPath();
- sourcePaths[i]= locations[i].getSystemLibrarySourcePath();
- sourceRootPaths[i]= locations[i].getPackageRootPath();
- }
- }
- locations = new LibraryLocation[sourcePaths.length];
- for (int i = 0; i < sourcePaths.length; i++) {
- locations[i] = new LibraryLocation(libraryPaths[i], sourcePaths[i], sourceRootPaths[i]);
- }
- return locations;
- }
-
- /**
- * 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(new Path(JRE_CONTAINER));
- }
-
- /**
- * Returns the VM connetor 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
- */
- public static Preferences getPreferences() {
- return LaunchingPlugin.getDefault().getPluginPreferences();
- }
-
- /**
- * Saves the preferences for the launching plug-in.
- *
- * @since 2.0
- */
- public static void savePreferences() {
- LaunchingPlugin.getDefault().savePluginPreferences();
- }
-
- /**
- * Registers the given resolver for the specified variable.
- *
- * @param resolver runtime classpathe entry resolver
- * @param variableName variable name to register for
- * @since 2.0
- */
- public static void addVariableResolver(IRuntimeClasspathEntryResolver resolver, String variableName) {
- Map map = getVariableResolvers();
- map.put(variableName, resolver);
- }
-
- /**
- * Registers the given resolver for the specified container.
- *
- * @param resolver runtime classpathe entry resolver
- * @param containerIdentifier identifier of the classpath container to register for
- * @since 2.0
- */
- public static void addContainerResolver(IRuntimeClasspathEntryResolver resolver, String containerIdentifier) {
- Map map = getContainerResolvers();
- map.put(containerIdentifier, resolver);
- }
-
- /**
- * Returns all registered variable resolvers.
- */
- private static Map getVariableResolvers() {
- if (fgVariableResolvers == null) {
- initializeResolvers();
- }
- return fgVariableResolvers;
- }
-
- /**
- * Returns all registered container resolvers.
- */
- private static Map getContainerResolvers() {
- if (fgContainerResolvers == null) {
- initializeResolvers();
- }
- return fgContainerResolvers;
- }
-
- private static void initializeResolvers() {
- IExtensionPoint point = LaunchingPlugin.getDefault().getDescriptor().getExtensionPoint(EXTENSION_POINT_RUNTIME_CLASSPATH_ENTRY_RESOLVERS);
- IConfigurationElement[] extensions = point.getConfigurationElements();
- fgVariableResolvers = new HashMap(extensions.length);
- fgContainerResolvers = 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();
- if (variable != null) {
- fgVariableResolvers.put(variable, res);
- }
- if (container != null) {
- fgContainerResolvers.put(container, res);
- }
- }
- }
-
- /**
- * Returns all registered classpath providers.
- */
- private static Map getClasspathProviders() {
- if (fgPathProviders == null) {
- initializeProviders();
- }
- return fgPathProviders;
- }
-
- private static void initializeProviders() {
- IExtensionPoint point = LaunchingPlugin.getDefault().getDescriptor().getExtensionPoint(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 resovler registered for the give variable, or
- * <code>null</code> if none.
- *
- * @return the resovler registered for the give variable, or
- * <code>null</code> if none
- */
- private static IRuntimeClasspathEntryResolver getVariableResolver(String variableName) {
- return (IRuntimeClasspathEntryResolver)getVariableResolvers().get(variableName);
- }
-
- /**
- * Returns the resovler registered for the give container id, or
- * <code>null</code> if none.
- *
- * @return the resovler registered for the give container id, or
- * <code>null</code> if none
- */
- private static IRuntimeClasspathEntryResolver getContainerResolver(String containerId) {
- return (IRuntimeClasspathEntryResolver)getContainerResolvers().get(containerId);
- }
-
- /**
- * Returns the provider registered for the given identifier, or
- * <code>null</code> if none.
- *
- * @return the provider registered for the given identifier, or
- * <code>null</code> if none
- */
- private static IRuntimeClasspathProvider getClasspathProvider(String identifier) {
- return (IRuntimeClasspathProvider)getClasspathProviders().get(identifier);
- }
-
- /**
- * 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);
- }
-
- private static void notifyDefaultVMChanged(IVMInstall previous, IVMInstall current) {
- Object[] listeners = fgVMListeners.getListeners();
- for (int i = 0; i < listeners.length; i++) {
- IVMInstallChangedListener listener = (IVMInstallChangedListener)listeners[i];
- listener.defaultVMInstallChanged(previous, current);
- }
- }
-
- /**
- * Notifies all VM install changed listeners of the given property change.
- *
- * @param vm the VM that has changed
- * @param event event desribing the change.
- * @since 2.0
- */
- public static void fireVMChanged(PropertyChangeEvent event) {
- Object[] listeners = fgVMListeners.getListeners();
- for (int i = 0; i < listeners.length; i++) {
- IVMInstallChangedListener listener = (IVMInstallChangedListener)listeners[i];
- 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) {
- Object[] listeners = fgVMListeners.getListeners();
- for (int i = 0; i < listeners.length; i++) {
- IVMInstallChangedListener listener = (IVMInstallChangedListener)listeners[i];
- 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) {
- Object[] listeners = fgVMListeners.getListeners();
- for (int i = 0; i < listeners.length; i++) {
- IVMInstallChangedListener listener = (IVMInstallChangedListener)listeners[i];
- listener.vmRemoved(vm);
- }
- }
+package org.eclipse.jdt.launching;
+
+/*******************************************************************************
+ * Copyright (c) 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.xerces.dom.DocumentImpl;
+import org.eclipse.core.resources.IResource;
+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.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.debug.core.ILaunchConfiguration;
+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.JavaCore;
+import org.eclipse.jdt.internal.launching.CompositeId;
+import org.eclipse.jdt.internal.launching.JREContainerInitializer;
+import org.eclipse.jdt.internal.launching.JavaClasspathVariablesInitializer;
+import org.eclipse.jdt.internal.launching.JavaLaunchConfigurationUtils;
+import org.eclipse.jdt.internal.launching.LaunchingMessages;
+import org.eclipse.jdt.internal.launching.LaunchingPlugin;
+import org.eclipse.jdt.internal.launching.ListenerList;
+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.w3c.dom.Document;
+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 classpaths and source lookup paths for launch
+ * configurations.
+ * <p>
+ * This class provides static methods only; it is not intended to be
+ * instantiated or subclassed by clients.
+ * </p>
+ */
+public final class JavaRuntime {
+
+ /**
+ * Classpath variable name used for the default JRE's library.
+ */
+ public static final String JRELIB_VARIABLE= "JRE_LIB"; //$NON-NLS-1$
+
+ /**
+ * Classpath variable name used for the default JRE's library source.
+ */
+ public static final String JRESRC_VARIABLE= "JRE_SRC"; //$NON-NLS-1$
+
+ /**
+ * Classpath variable name used for the default JRE's library source root.
+ */
+ 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$
+
+ /**
+ * Classpath container used for a project's JRE. 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>
+ *
+ * @since 2.0
+ */
+ public static final String JRE_CONTAINER = LaunchingPlugin.getUniqueIdentifier() + ".JRE_CONTAINER"; //$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 millieseconds.
+ *
+ * @since 2.0
+ */
+ public static final String PREF_CONNECT_TIMEOUT = LaunchingPlugin.getUniqueIdentifier() + ".PREF_CONNECT_TIMEOUT"; //$NON-NLS-1$
+
+ /**
+ * Default launch/connect timeout (ms).
+ *
+ * @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.
+ */
+ public final static String ATTR_CMDLINE= LaunchingPlugin.getUniqueIdentifier() + ".launcher.cmdLine"; //$NON-NLS-1$
+
+ private static IVMInstallType[] fgVMTypes= null;
+ private static String fgDefaultVMId= null;
+ private static String fgDefaultVMConnectorId = null;
+
+ /**
+ * Resolvers keyed by variable name and container id.
+ */
+ private static Map fgVariableResolvers = null;
+ private static Map fgContainerResolvers = null;
+
+ /**
+ * Path providers keyed by id
+ */
+ private static Map 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 fgVMListeners = new ListenerList(5);
+
+ /**
+ * Not intended to be instantiated.
+ */
+ private JavaRuntime() {
+ }
+
+ /**
+ * 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() {
+ if (fgVMTypes == null) {
+ initializeVMTypes();
+ }
+ return fgVMTypes;
+ }
+
+ private static synchronized void initializeVMTypes() {
+ IExtensionPoint extensionPoint= Platform.getPluginRegistry().getExtensionPoint(LaunchingPlugin.getUniqueIdentifier() + ".vmInstallTypes"); //$NON-NLS-1$
+ IConfigurationElement[] configs= extensionPoint.getConfigurationElements();
+ MultiStatus status= new MultiStatus(LaunchingPlugin.getUniqueIdentifier(), IStatus.OK, LaunchingMessages.getString("JavaRuntime.exceptionOccurred"), null); //$NON-NLS-1$
+ fgVMTypes= new IVMInstallType[configs.length];
+
+ for (int i= 0; i < configs.length; i++) {
+ try {
+ IVMInstallType vmType= (IVMInstallType)configs[i].createExecutableExtension("class"); //$NON-NLS-1$
+ fgVMTypes[i]= vmType;
+ } catch (CoreException e) {
+ status.add(e.getStatus());
+ }
+ }
+ if (!status.isOK()) {
+ //only happens on a CoreException
+ LaunchingPlugin.log(status);
+ //cleanup null entries in fgVMTypes
+ List temp= new ArrayList(fgVMTypes.length);
+ for (int i = 0; i < fgVMTypes.length; i++) {
+ if(fgVMTypes[i] != null) {
+ temp.add(fgVMTypes[i]);
+ }
+ fgVMTypes= new IVMInstallType[temp.size()];
+ fgVMTypes= (IVMInstallType[])temp.toArray(fgVMTypes);
+ }
+ }
+
+ try {
+ initializeVMConfiguration();
+ } catch (IOException e) {
+ LaunchingPlugin.log(e);
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @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;
+ for (int i = 0; i < classpath.length; i++) {
+ IClasspathEntry 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;
+ }
+
+ private static IVMInstall getVMFromId(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 the VM install type with the given 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>
+ */
+ public static void setDefaultVMInstall(IVMInstall vm, IProgressMonitor monitor) throws CoreException {
+ IVMInstall previous = null;
+ if (fgDefaultVMId != null) {
+ previous = getVMFromId(fgDefaultVMId);
+ }
+ fgDefaultVMId= getIdFromVM(vm);
+ updateJREVariables(monitor);
+ saveVMConfiguration();
+ IVMInstall current = null;
+ if (fgDefaultVMId != null) {
+ current = getVMFromId(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 null to clear
+ * the default.
+ * @since 2.0
+ */
+ public static void setDefaultVMConnector(IVMConnector connector, IProgressMonitor monitor) throws CoreException {
+ fgDefaultVMConnectorId= connector.getIdentifier();
+ saveVMConfiguration();
+ }
+
+ private static void updateJREVariables(IProgressMonitor monitor) throws CoreException {
+ JavaClasspathVariablesInitializer updater= new JavaClasspathVariablesInitializer();
+ updater.updateJREVariables(monitor);
+ JREContainerInitializer conatinerUpdater = new JREContainerInitializer();
+ conatinerUpdater.updateDefaultJREContainers(monitor);
+ }
+ /**
+ * 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= getVMFromId(getDefaultVMId());
+ if (install != null && install.getInstallLocation().exists()) {
+ return install;
+ } else {
+ // if the default JRE goes missing, re-detect
+ if (install != null) {
+ install.getVMInstallType().disposeVMInstall(install.getId());
+ }
+ fgDefaultVMId = null;
+ try {
+ //get rid of bad values on disk
+ saveVMConfiguration();
+ } catch(CoreException e) {
+ LaunchingPlugin.log(e);
+ }
+ detectVMConfiguration();
+ return getVMFromId(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;
+ }
+
+ private static String getDefaultVMId() {
+ if (fgVMTypes == null) {
+ initializeVMTypes();
+ }
+ return fgDefaultVMId;
+ }
+
+ private static String getDefaultVMConnectorId() {
+ if (fgVMTypes == null) {
+ initializeVMTypes();
+ }
+ return fgDefaultVMConnectorId;
+ }
+
+ private static String getIdFromVM(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();
+ }
+
+ /**
+ * 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) {
+ IClasspathEntry cpe = JavaCore.newProjectEntry(project.getProject().getFullPath());
+ return newRuntimeClasspathEntry(cpe);
+ }
+
+
+ /**
+ * 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) {
+ IClasspathEntry cpe = JavaCore.newLibraryEntry(resource.getFullPath(), null, null);
+ return newRuntimeClasspathEntry(cpe);
+ }
+
+ /**
+ * 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) {
+ IClasspathEntry cpe = JavaCore.newLibraryEntry(path, null, null);
+ return newRuntimeClasspathEntry(cpe);
+ }
+
+ /**
+ * 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) {
+ IClasspathEntry cpe = JavaCore.newVariableEntry(path, null, null);
+ return newRuntimeClasspathEntry(cpe);
+ }
+
+ /**
+ * 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>, or <code>STANDARD_CLASSES</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 {
+ IClasspathEntry cpe = JavaCore.newContainerEntry(path);
+ return new RuntimeClasspathEntry(cpe, classpathProperty);
+ }
+
+ /**
+ * Returns a runtime classpath entry constructed from the given memento.
+ *
+ * @param memento a menento 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 {
+ return new RuntimeClasspathEntry(memento);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Computes and returns the default unresolved runtime claspath for the
+ * given project.
+ *
+ * @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 entry = JavaCore.newProjectEntry(project.getProject().getFullPath());
+ List classpathEntries = new ArrayList(5);
+ List expanding = new ArrayList(5);
+ expandProject(entry, classpathEntries, expanding);
+ IRuntimeClasspathEntry[] runtimeEntries = new IRuntimeClasspathEntry[classpathEntries == null ? 0 : classpathEntries.size()];
+ for (int i = 0; i < runtimeEntries.length; i++) {
+ Object e = classpathEntries.get(i);
+ if (e instanceof IClasspathEntry) {
+ IClasspathEntry cpe = (IClasspathEntry)e;
+ runtimeEntries[i] = newRuntimeClasspathEntry(cpe);
+ } else {
+ runtimeEntries[i] = (IRuntimeClasspathEntry)e;
+ }
+ }
+ // sort bootpath and standard entries first
+ IRuntimeClasspathEntry[] ordered = new IRuntimeClasspathEntry[runtimeEntries.length];
+ int index = 0;
+ for (int i = 0; i < runtimeEntries.length; i++) {
+ if (runtimeEntries[i].getClasspathProperty() != IRuntimeClasspathEntry.USER_CLASSES) {
+ ordered[index] = runtimeEntries[i];
+ index++;
+ runtimeEntries[i] = null;
+ }
+ }
+ for (int i = 0; i < runtimeEntries.length; i++) {
+ if (runtimeEntries[i] != null) {
+ ordered[index] = runtimeEntries[i];
+ index++;
+ }
+ }
+ return ordered;
+ }
+
+ /**
+ * 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 = (IRuntimeClasspathProvider)getClasspathProviders().get(providerId);
+ }
+ 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 = (IRuntimeClasspathProvider)getClasspathProviders().get(providerId);
+ }
+ 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>CONTAINTER</code>, variable and contanier
+ * resolvers are consulted, otherwise, the returned entry is the same as the
+ * given entry.
+ * <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.VARIABLE:
+ IRuntimeClasspathEntryResolver resolver = getVariableResolver(entry.getVariableName());
+ if (resolver == null) {
+ // no resolution by default
+ break;
+ } else {
+ return resolver.resolveRuntimeClasspathEntry(entry, configuration);
+ }
+ case IRuntimeClasspathEntry.CONTAINER:
+ resolver = getContainerResolver(entry.getVariableName());
+ if (resolver == null) {
+ return computeDefaultContainerEntries(entry, configuration);
+ } else {
+ return resolver.resolveRuntimeClasspathEntry(entry, configuration);
+ }
+ default:
+ break;
+ }
+ return new IRuntimeClasspathEntry[] {entry};
+ }
+
+ /**
+ * 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>CONTAINTER</code>, variable and contanier
+ * resolvers are consulted, otherwise, the returned entry is the same as the given
+ * entry.
+ * <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.VARIABLE:
+ IRuntimeClasspathEntryResolver resolver = getVariableResolver(entry.getVariableName());
+ if (resolver == null) {
+ // no resolution by default
+ break;
+ } else {
+ return resolver.resolveRuntimeClasspathEntry(entry, project);
+ }
+ case IRuntimeClasspathEntry.CONTAINER:
+ resolver = getContainerResolver(entry.getVariableName());
+ if (resolver == null) {
+ return computeDefaultContainerEntries(entry, project);
+ } else {
+ return resolver.resolveRuntimeClasspathEntry(entry, project);
+ }
+ default:
+ break;
+ }
+ return new IRuntimeClasspathEntry[] {entry};
+ }
+
+ /**
+ * Performs default resolution for a container entry.
+ * Delegates to the Java model.
+ */
+ private static IRuntimeClasspathEntry[] computeDefaultContainerEntries(IRuntimeClasspathEntry entry, ILaunchConfiguration config) throws CoreException {
+ return computeDefaultContainerEntries(entry, getJavaProject(config));
+ }
+
+ /**
+ * Performs default resolution for a container entry.
+ * Delegates to the Java model.
+ */
+ private static IRuntimeClasspathEntry[] computeDefaultContainerEntries(IRuntimeClasspathEntry entry, IJavaProject project) throws CoreException {
+ if (project == null) {
+ // cannot resolve without project context
+ return new IRuntimeClasspathEntry[0];
+ } else {
+ IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
+ 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;
+ }
+ IRuntimeClasspathEntry[] resolved = new IRuntimeClasspathEntry[cpes.length];
+ for (int i = 0; i < resolved.length; i++) {
+ resolved[i] = newRuntimeClasspathEntry(cpes[i]);
+ resolved[i].setClasspathProperty(property);
+ }
+ return resolved;
+ }
+ }
+
+ /**
+ * 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 {
+ return getClasspathProvider(configuration).resolveClasspath(entries, configuration);
+ }
+
+ /**
+ * Return the <code>IJavaProject</code> referenced in the specified configuration or
+ * <code>null</code> if none.
+ *
+ * @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.exists()) {
+ abort(MessageFormat.format(LaunchingMessages.getString("JavaRuntime.Launch_configuration_{0}_references_non-existing_project_{1}._1"), new String[] {configuration.getName(), projectName}), IJavaLaunchConfigurationConstants.ERR_NOT_A_JAVA_PROJECT, null); //$NON-NLS-1$
+ }
+ return javaProject;
+ }
+
+ /**
+ * Convenience method to get the java model.
+ */
+ private static IJavaModel getJavaModel() {
+ return JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
+ }
+
+
+ /**
+ * Returns a collection of runtime classpath entries that are defined in the
+ * specified attribute of the given launch configuration.
+ *
+ * @param configuration launch configuration
+ * @param attribute attribute name containing the list of entries
+ * @return collection of runtime classpath entries that are defined in the
+ * specified attribute of the given launch configuration
+ * @exception CoreException if unable to retrieve the list
+ */
+ private static IRuntimeClasspathEntry[] recoverRuntimePath(ILaunchConfiguration configuration, String attribute) throws CoreException {
+ List entries = (List)configuration.getAttribute(attribute, Collections.EMPTY_LIST);
+ IRuntimeClasspathEntry[] rtes = new IRuntimeClasspathEntry[entries.size()];
+ Iterator iter = entries.iterator();
+ int i = 0;
+ while (iter.hasNext()) {
+ rtes[i] = newRuntimeClasspathEntry((String)iter.next());
+ i++;
+ }
+ return rtes;
+ }
+
+ /**
+ * 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_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 confiugration'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 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 {
+ IVMInstallType vt = getVMInstallType(type);
+ if (vt == null) {
+ // error type does not exist
+ abort(MessageFormat.format(LaunchingMessages.getString("JavaRuntime.Specified_VM_install_type_does_not_exist__{0}_2"), new String[] {type}), null); //$NON-NLS-1$
+ }
+ IVMInstall vm = null;
+ // look for a name
+ String name = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME, (String)null);
+ 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.
+ IStatus status = new Status(IStatus.WARNING, LaunchingPlugin.getUniqueIdentifier(), IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_VM_INSTALL, MessageFormat.format(LaunchingMessages.getString("JavaRuntime.VM_not_fully_specified_in_launch_configuration_{0}_-_missing_VM_name._Reverting_to_default_VM._1"), new String[] {configuration.getName()}), null); //$NON-NLS-1$
+ LaunchingPlugin.log(status);
+ return getDefaultVMInstall();
+ } else {
+ vm = vt.findVMInstallByName(name);
+ if (vm == null) {
+ // error - install not found
+ abort(MessageFormat.format(LaunchingMessages.getString("JavaRuntime.Specified_VM_install_not_found__type_{0},_name_{1}_2"), new String[] {type, name}), null); //$NON-NLS-1$
+ } else {
+ return vm;
+ }
+ }
+ }
+
+ return getDefaultVMInstall();
+ }
+
+ /**
+ * Throws a core exception with an internal error status.
+ *
+ * @param message the status message
+ * @param exception lower level exception associated with the
+ * error, or <code>null</code> if none
+ */
+ private static 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
+ */
+ private static void abort(String message, int code, Throwable exception) throws CoreException {
+ throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), code, message, exception));
+ }
+
+ /**
+ * Returns the transitive closure of classpath entries for the
+ * given project entry.
+ *
+ * @param projectEntry project classpath entry
+ * @param a list of entries already expanded, should be empty to begin,
+ * and contains the result
+ * @param expanding a list of project that have been or currently are being
+ * expanded (to detect cycles in the classpath)
+ * @exception CoreException if unable to expand the classpath
+ */
+ private static void expandProject(IClasspathEntry projectEntry, List expandedPath, List expanding) throws CoreException {
+ expanding.add(projectEntry);
+ // 1. Get the raw classpath
+ // 2. Replace source folder entries with a project entry
+ IPath projectPath = projectEntry.getPath();
+ IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(projectPath.lastSegment());
+ if (res == null) {
+ return;
+ }
+ IJavaProject project = (IJavaProject)JavaCore.create(res);
+ if (project == null) {
+ return;
+ }
+ IClasspathEntry[] buildPath = project.getRawClasspath();
+ List unexpandedPath = new ArrayList(buildPath.length);
+ boolean projectAdded = false;
+ for (int i = 0; i < buildPath.length; i++) {
+ if (buildPath[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ if (!projectAdded) {
+ projectAdded = true;
+ unexpandedPath.add(projectEntry);
+ }
+ } else {
+ unexpandedPath.add(buildPath[i]);
+ }
+ }
+ // 3. expand each project entry (except for the root project)
+ // 4. replace each container entry with a runtime entry associated with the project
+ Iterator iter = unexpandedPath.iterator();
+ while (iter.hasNext()) {
+ IClasspathEntry entry = (IClasspathEntry)iter.next();
+ if (entry == projectEntry) {
+ expandedPath.add(entry);
+ } else {
+ switch (entry.getEntryKind()) {
+ case IClasspathEntry.CPE_PROJECT:
+ if (!expanding.contains(entry)) {
+ expandProject(entry, expandedPath, expanding);
+ }
+ break;
+ case IClasspathEntry.CPE_CONTAINER:
+ IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), project);
+ 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;
+ }
+ IRuntimeClasspathEntry r = newRuntimeContainerClasspathEntry(entry.getPath(), property);
+ // check for duplicate/redundant entries
+ boolean duplicate = false;
+ for (int i = 0; i < expandedPath.size(); i++) {
+ Object o = expandedPath.get(i);
+ if (o instanceof IRuntimeClasspathEntry) {
+ IRuntimeClasspathEntry re = (IRuntimeClasspathEntry)o;
+ if (re.getType() == IRuntimeClasspathEntry.CONTAINER) {
+ if (container instanceof IRuntimeContainerComparator) {
+ duplicate = ((IRuntimeContainerComparator)container).isDuplicate(re.getPath());
+ if (duplicate) {
+ break;
+ }
+ } else if (re.getVariableName().equals(r.getVariableName())) {
+ duplicate = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!duplicate) {
+ expandedPath.add(r);
+ }
+ break;
+ case IClasspathEntry.CPE_VARIABLE:
+ if (entry.getPath().segment(0).equals(JRELIB_VARIABLE)) {
+ r = newVariableRuntimeClasspathEntry(entry.getPath());
+ r.setSourceAttachmentPath(entry.getSourceAttachmentPath());
+ r.setSourceAttachmentRootPath(entry.getSourceAttachmentRootPath());
+ r.setClasspathProperty(IRuntimeClasspathEntry.STANDARD_CLASSES);
+ if (!expandedPath.contains(r)) {
+ expandedPath.add(r);
+ }
+ break;
+ }
+ // fall through if not the special JRELIB variable
+ default:
+ if (!expandedPath.contains(entry)) {
+ expandedPath.add(entry);
+ }
+ break;
+ }
+ }
+ }
+ return;
+ }
+
+ /**
+ * 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 resolved = new ArrayList(unresolved.length);
+ for (int i = 0; i < unresolved.length; i++) {
+ IRuntimeClasspathEntry entry = unresolved[i];
+ if (unresolved[i].getClasspathProperty() == IRuntimeClasspathEntry.USER_CLASSES) {
+ switch (entry.getType()) {
+ case IRuntimeClasspathEntry.CONTAINER:
+ IRuntimeClasspathEntry[] contained = computeDefaultContainerEntries(entry, jproject);
+ for (int j = 0; j < contained.length; j++) {
+ resolved.add(contained[j].getLocation());
+ }
+ break;
+ default:
+ resolved.add(entry.getLocation());
+ break;
+ }
+ }
+ }
+ return (String[])resolved.toArray(new String[resolved.size()]);
+ }
+
+ /**
+ * Saves the VM configuration information to disk. 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.
+ */
+ public static void saveVMConfiguration() throws CoreException {
+ IPath stateLocation= LaunchingPlugin.getDefault().getStateLocation();
+ IPath stateFile= stateLocation.append("vmConfiguration.xml"); //$NON-NLS-1$
+ File f= new File(stateFile.toOSString());
+ try {
+ String xml = getVMsAsXML();
+ FileOutputStream stream = new FileOutputStream(f);
+ stream.write(xml.getBytes("UTF8")); //$NON-NLS-1$
+ stream.close();
+ } catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), IStatus.ERROR, LaunchingMessages.getString("JavaRuntime.ioExceptionOccurred"), e)); //$NON-NLS-1$
+ }
+
+ }
+
+ private static String getVMsAsXML() throws IOException {
+ Document doc = new DocumentImpl();
+ Element config = doc.createElement("vmSettings"); //$NON-NLS-1$
+ if (fgDefaultVMId != null) {
+ config.setAttribute("defaultVM", fgDefaultVMId); //$NON-NLS-1$
+ }
+ if (fgDefaultVMConnectorId != null) {
+ config.setAttribute("defaultVMConnector", fgDefaultVMConnectorId); //$NON-NLS-1$
+ }
+ doc.appendChild(config);
+
+ IVMInstallType[] vmTypes= getVMInstallTypes();
+
+ for (int i = 0; i < vmTypes.length; ++i) {
+ Element vmTypeElement = vmTypeAsElement(doc, vmTypes[i]);
+ config.appendChild(vmTypeElement);
+ }
+
+ return JavaLaunchConfigurationUtils.serializeDocument(doc);
+ }
+
+ private static Element vmTypeAsElement(Document doc, IVMInstallType vmType) {
+ Element element= doc.createElement("vmType"); //$NON-NLS-1$
+ element.setAttribute("id", vmType.getId()); //$NON-NLS-1$
+ IVMInstall[] vms= vmType.getVMInstalls();
+ for (int i= 0; i < vms.length; i++) {
+ Element vmElement= vmAsElement(doc, vms[i]);
+ element.appendChild(vmElement);
+ }
+ return element;
+ }
+
+ private static Element vmAsElement(Document doc, IVMInstall vm) {
+ Element element= doc.createElement("vm"); //$NON-NLS-1$
+ element.setAttribute("id", vm.getId()); //$NON-NLS-1$
+ element.setAttribute("name", vm.getName()); //$NON-NLS-1$
+ String installPath= ""; //$NON-NLS-1$
+ File installLocation= vm.getInstallLocation();
+ if (installLocation != null) {
+ installPath= installLocation.getAbsolutePath();
+ }
+ element.setAttribute("path", installPath); //$NON-NLS-1$
+ LibraryLocation[] libraryLocations= vm.getLibraryLocations();
+ if (libraryLocations != null) {
+ Element libLocationElement= libraryLocationsAsElement(doc, libraryLocations);
+ element.appendChild(libLocationElement);
+ }
+ return element;
+ }
+
+ private static Element libraryLocationsAsElement(Document doc, LibraryLocation[] locations) {
+ Element root = doc.createElement("libraryLocations"); //$NON-NLS-1$
+ for (int i = 0; i < locations.length; i++) {
+ Element element= doc.createElement("libraryLocation"); //$NON-NLS-1$
+ element.setAttribute("jreJar", locations[i].getSystemLibraryPath().toString()); //$NON-NLS-1$
+ element.setAttribute("jreSrc", locations[i].getSystemLibrarySourcePath().toString()); //$NON-NLS-1$
+ element.setAttribute("pkgRoot", locations[i].getPackageRootPath().toString()); //$NON-NLS-1$
+ root.appendChild(element);
+ }
+ return root;
+ }
+
+ private static void initializeVMConfiguration() throws IOException {
+ IPath stateLocation= LaunchingPlugin.getDefault().getStateLocation();
+ IPath stateFile= stateLocation.append("vmConfiguration.xml"); //$NON-NLS-1$
+ File f= new File(stateFile.toOSString());
+ if (f.isFile()) {
+ loadVMConfiguration(f);
+ } else {
+ detectVMConfiguration();
+ }
+ }
+
+ private static void loadVMConfiguration(File f) throws IOException {
+ InputStream stream= new BufferedInputStream(new FileInputStream(f));
+ Reader reader= new InputStreamReader(stream, "UTF-8"); //$NON-NLS-1$
+ Element config= null;
+ try {
+ DocumentBuilder parser= DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ config = parser.parse(new InputSource(reader)).getDocumentElement();
+ } catch (SAXException e) {
+ throw new IOException(LaunchingMessages.getString("JavaRuntime.badFormat")); //$NON-NLS-1$
+ } catch (ParserConfigurationException e) {
+ reader.close();
+ throw new IOException(LaunchingMessages.getString("JavaRuntime.badFormat")); //$NON-NLS-1$
+ } finally {
+ reader.close();
+ }
+ if (!config.getNodeName().equalsIgnoreCase("vmSettings")) { //$NON-NLS-1$
+ throw new IOException(LaunchingMessages.getString("JavaRuntime.badFormat")); //$NON-NLS-1$
+ }
+ fgDefaultVMId= config.getAttribute("defaultVM"); //$NON-NLS-1$
+ fgDefaultVMConnectorId = config.getAttribute("defaultVMConnector"); //$NON-NLS-1$
+ NodeList list = config.getChildNodes();
+ int length = list.getLength();
+ for (int i = 0; i < length; ++i) {
+ Node node = list.item(i);
+ short type = node.getNodeType();
+ if (type == Node.ELEMENT_NODE) {
+ Element vmTypeElement = (Element) node;
+ if (vmTypeElement.getNodeName().equalsIgnoreCase("vmType")) { //$NON-NLS-1$
+ createFromVMType(vmTypeElement);
+ }
+ }
+ }
+ }
+
+ private static void detectVMConfiguration() {
+ IVMInstallType[] vmTypes= getVMInstallTypes();
+ boolean defaultSet= false;
+ for (int i= 0; i < vmTypes.length; i++) {
+ File detectedLocation= vmTypes[i].detectInstallLocation();
+ if (detectedLocation != null) {
+ int unique = i;
+ IVMInstallType vmType = vmTypes[i];
+ while (vmType.findVMInstall(String.valueOf(unique)) != null) {
+ unique++;
+ }
+ IVMInstall detected= vmTypes[i].createVMInstall(String.valueOf(unique));
+ detected.setName(LaunchingMessages.getString("JavaRuntime.detectedSuffix")); //$NON-NLS-1$
+ detected.setInstallLocation(detectedLocation);
+ if (detected != null && !defaultSet) {
+ try {
+ setDefaultVMInstall(detected, null);
+ defaultSet= true;
+ } catch (CoreException e) {
+ LaunchingPlugin.log(e);
+ }
+ }
+ }
+ }
+ }
+
+ private static void createFromVMType(Element vmTypeElement) {
+ String id = vmTypeElement.getAttribute("id"); //$NON-NLS-1$
+ IVMInstallType vmType= getVMInstallType(id);
+ if (vmType != null) {
+ NodeList list = vmTypeElement.getChildNodes();
+ int length = list.getLength();
+ for (int i = 0; i < length; ++i) {
+ Node node = list.item(i);
+ short type = node.getNodeType();
+ if (type == Node.ELEMENT_NODE) {
+ Element vmElement = (Element) node;
+ if (vmElement.getNodeName().equalsIgnoreCase("vm")) { //$NON-NLS-1$
+ createVM(vmType, vmElement);
+ }
+ }
+ }
+ } else {
+ LaunchingPlugin.log(LaunchingMessages.getString("JavaRuntime.VM_type_element_with_unknown_id_1")); //$NON-NLS-1$
+ }
+ }
+
+ private static void createVM(IVMInstallType vmType, Element vmElement) {
+ String id= vmElement.getAttribute("id"); //$NON-NLS-1$
+ if (id != null) {
+ String installPath= vmElement.getAttribute("path"); //$NON-NLS-1$
+ if (installPath == null) {
+ return;
+ }
+ File installLocation= new File(installPath);
+ if (!installLocation.exists()) {
+ return;
+ }
+ IVMInstall vm= vmType.createVMInstall(id);
+ vm.setName(vmElement.getAttribute("name")); //$NON-NLS-1$
+ vm.setInstallLocation(installLocation);
+
+ NodeList list = vmElement.getChildNodes();
+ int length = list.getLength();
+ for (int i = 0; i < length; ++i) {
+ Node node = list.item(i);
+ short type = node.getNodeType();
+ if (type == Node.ELEMENT_NODE) {
+ Element libraryLocationElement= (Element)node;
+ if (libraryLocationElement.getNodeName().equals("libraryLocation")) { //$NON-NLS-1$
+ LibraryLocation loc = getLibraryLocation(vm, libraryLocationElement);
+ vm.setLibraryLocations(new LibraryLocation[]{loc});
+ break;
+ } else if (libraryLocationElement.getNodeName().equals("libraryLocations")) { //$NON-NLS-1$
+ setLibraryLocations(vm, libraryLocationElement);
+ break;
+ }
+ }
+ }
+
+ } else {
+ LaunchingPlugin.log(LaunchingMessages.getString("JavaRuntime.VM_element_specified_with_no_id_attribute_2")); //$NON-NLS-1$
+ }
+ }
+
+ private static LibraryLocation getLibraryLocation(IVMInstall vm, Element libLocationElement) {
+ String jreJar= libLocationElement.getAttribute("jreJar"); //$NON-NLS-1$
+ String jreSrc= libLocationElement.getAttribute("jreSrc"); //$NON-NLS-1$
+ String pkgRoot= libLocationElement.getAttribute("pkgRoot"); //$NON-NLS-1$
+ if (jreJar != null && jreSrc != null && pkgRoot != null) {
+ return new LibraryLocation(new Path(jreJar), new Path(jreSrc), new Path(pkgRoot));
+ } else {
+ LaunchingPlugin.log(LaunchingMessages.getString("JavaRuntime.Library_location_element_incorrectly_specified_3")); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ private static void setLibraryLocations(IVMInstall vm, Element libLocationsElement) {
+ NodeList list = libLocationsElement.getChildNodes();
+ int length = list.getLength();
+ List locations = new ArrayList(length);
+ for (int i = 0; i < length; ++i) {
+ Node node = list.item(i);
+ short type = node.getNodeType();
+ if (type == Node.ELEMENT_NODE) {
+ Element libraryLocationElement= (Element)node;
+ if (libraryLocationElement.getNodeName().equals("libraryLocation")) { //$NON-NLS-1$
+ locations.add(getLibraryLocation(vm, libraryLocationElement));
+ }
+ }
+ }
+ vm.setLibraryLocations((LibraryLocation[])locations.toArray(new LibraryLocation[locations.size()]));
+ }
+
+ /**
+ * 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.
+ * @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;
+ LibraryLocation[] locations= vm.getLibraryLocations();
+ if (locations == null) {
+ LibraryLocation[] dflts= vm.getVMInstallType().getDefaultLibraryLocations(vm.getInstallLocation());
+ libraryPaths = new IPath[dflts.length];
+ sourcePaths = new IPath[dflts.length];
+ sourceRootPaths = new IPath[dflts.length];
+ for (int i = 0; i < dflts.length; i++) {
+ libraryPaths[i]= dflts[i].getSystemLibraryPath();
+ if (!libraryPaths[i].toFile().isFile()) {
+ libraryPaths[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];
+ for (int i = 0; i < locations.length; i++) {
+ libraryPaths[i]= locations[i].getSystemLibraryPath();
+ sourcePaths[i]= locations[i].getSystemLibrarySourcePath();
+ sourceRootPaths[i]= locations[i].getPackageRootPath();
+ }
+ }
+ locations = new LibraryLocation[sourcePaths.length];
+ for (int i = 0; i < sourcePaths.length; i++) {
+ locations[i] = new LibraryLocation(libraryPaths[i], sourcePaths[i], sourceRootPaths[i]);
+ }
+ return locations;
+ }
+
+ /**
+ * 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(new Path(JRE_CONTAINER));
+ }
+
+ /**
+ * Returns the VM connetor 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
+ */
+ public static Preferences getPreferences() {
+ return LaunchingPlugin.getDefault().getPluginPreferences();
+ }
+
+ /**
+ * Saves the preferences for the launching plug-in.
+ *
+ * @since 2.0
+ */
+ public static void savePreferences() {
+ LaunchingPlugin.getDefault().savePluginPreferences();
+ }
+
+ /**
+ * Registers the given resolver for the specified variable.
+ *
+ * @param resolver runtime classpathe entry resolver
+ * @param variableName variable name to register for
+ * @since 2.0
+ */
+ public static void addVariableResolver(IRuntimeClasspathEntryResolver resolver, String variableName) {
+ Map map = getVariableResolvers();
+ map.put(variableName, resolver);
+ }
+
+ /**
+ * Registers the given resolver for the specified container.
+ *
+ * @param resolver runtime classpathe entry resolver
+ * @param containerIdentifier identifier of the classpath container to register for
+ * @since 2.0
+ */
+ public static void addContainerResolver(IRuntimeClasspathEntryResolver resolver, String containerIdentifier) {
+ Map map = getContainerResolvers();
+ map.put(containerIdentifier, resolver);
+ }
+
+ /**
+ * Returns all registered variable resolvers.
+ */
+ private static Map getVariableResolvers() {
+ if (fgVariableResolvers == null) {
+ initializeResolvers();
+ }
+ return fgVariableResolvers;
+ }
+
+ /**
+ * Returns all registered container resolvers.
+ */
+ private static Map getContainerResolvers() {
+ if (fgContainerResolvers == null) {
+ initializeResolvers();
+ }
+ return fgContainerResolvers;
+ }
+
+ private static void initializeResolvers() {
+ IExtensionPoint point = LaunchingPlugin.getDefault().getDescriptor().getExtensionPoint(EXTENSION_POINT_RUNTIME_CLASSPATH_ENTRY_RESOLVERS);
+ IConfigurationElement[] extensions = point.getConfigurationElements();
+ fgVariableResolvers = new HashMap(extensions.length);
+ fgContainerResolvers = 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();
+ if (variable != null) {
+ fgVariableResolvers.put(variable, res);
+ }
+ if (container != null) {
+ fgContainerResolvers.put(container, res);
+ }
+ }
+ }
+
+ /**
+ * Returns all registered classpath providers.
+ */
+ private static Map getClasspathProviders() {
+ if (fgPathProviders == null) {
+ initializeProviders();
+ }
+ return fgPathProviders;
+ }
+
+ private static void initializeProviders() {
+ IExtensionPoint point = LaunchingPlugin.getDefault().getDescriptor().getExtensionPoint(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 resovler registered for the give variable, or
+ * <code>null</code> if none.
+ *
+ * @return the resovler registered for the give variable, or
+ * <code>null</code> if none
+ */
+ private static IRuntimeClasspathEntryResolver getVariableResolver(String variableName) {
+ return (IRuntimeClasspathEntryResolver)getVariableResolvers().get(variableName);
+ }
+
+ /**
+ * Returns the resovler registered for the give container id, or
+ * <code>null</code> if none.
+ *
+ * @return the resovler registered for the give container id, or
+ * <code>null</code> if none
+ */
+ private static IRuntimeClasspathEntryResolver getContainerResolver(String containerId) {
+ return (IRuntimeClasspathEntryResolver)getContainerResolvers().get(containerId);
+ }
+
+ /**
+ * Returns the provider registered for the given identifier, or
+ * <code>null</code> if none.
+ *
+ * @return the provider registered for the given identifier, or
+ * <code>null</code> if none
+ */
+ private static IRuntimeClasspathProvider getClasspathProvider(String identifier) {
+ return (IRuntimeClasspathProvider)getClasspathProviders().get(identifier);
+ }
+
+ /**
+ * 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);
+ }
+
+ private static void notifyDefaultVMChanged(IVMInstall previous, IVMInstall current) {
+ Object[] listeners = fgVMListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IVMInstallChangedListener listener = (IVMInstallChangedListener)listeners[i];
+ listener.defaultVMInstallChanged(previous, current);
+ }
+ }
+
+ /**
+ * Notifies all VM install changed listeners of the given property change.
+ *
+ * @param vm the VM that has changed
+ * @param event event desribing the change.
+ * @since 2.0
+ */
+ public static void fireVMChanged(PropertyChangeEvent event) {
+ Object[] listeners = fgVMListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IVMInstallChangedListener listener = (IVMInstallChangedListener)listeners[i];
+ 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) {
+ Object[] listeners = fgVMListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IVMInstallChangedListener listener = (IVMInstallChangedListener)listeners[i];
+ 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) {
+ Object[] listeners = fgVMListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IVMInstallChangedListener listener = (IVMInstallChangedListener)listeners[i];
+ listener.vmRemoved(vm);
+ }
+ }
}
\ No newline at end of file