blob: d2b4acb619fa755f98add7b95ee67b98bd7a4118 [file] [log] [blame]
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);
}
}
}