| 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); |
| } |
| } |
| } |