/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.launching;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.wst.jsdt.internal.core.util.Util;
/**
* A VM install type for VMs the conform to the standard
* JDK installion layout.
*
* Provisional API: This class/interface is part of an interim API that is still under development and expected to
* change significantly before reaching stability. It is being made available at this early stage to solicit feedback
* from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
* (repeatedly) as the API evolves.
*/
public class StandardVMType extends AbstractVMInstallType {
public static final String ID_STANDARD_VM_TYPE = "org.eclipse.wst.jsdt.internal.debug.ui.launcher.StandardVMType"; //$NON-NLS-1$
/**
* The root path for the attached src
*/
private String fDefaultRootPath;
/**
* Map of the install path for which we were unable to generate
* the library info during this session.
*/
// private static Map fgFailedInstallPath= new HashMap();
/**
* Convenience handle to the system-specific file separator character
*/
private static final char fgSeparator = File.separatorChar;
/**
* The list of locations in which to look for the javascript executable in candidate
* VM install locations, relative to the VM install location.
*/
private static final String[] fgCandidateJavaFiles = {"javaw", "javaw.exe", "java", "java.exe", "j9w", "j9w.exe", "j9", "j9.exe"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
private static final String[] fgCandidateJavaLocations = {"bin" + fgSeparator, "jre" + fgSeparator + "bin" + fgSeparator}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
/**
* Starting in the specified VM install location, attempt to find the 'java' executable
* file. If found, return the corresponding <code>File</code> object, otherwise return
* <code>null</code>.
*/
public static File findJavaExecutable(File vmInstallLocation) {
// Try each candidate in order. The first one found wins. Thus, the order
// of fgCandidateJavaLocations and fgCandidateJavaFiles is significant.
for (int i = 0; i < fgCandidateJavaFiles.length; i++) {
for (int j = 0; j < fgCandidateJavaLocations.length; j++) {
File javaFile = new File(vmInstallLocation, fgCandidateJavaLocations[j] + fgCandidateJavaFiles[i]);
if (javaFile.isFile()) {
return javaFile;
}
}
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.launching.IVMInstallType#getName()
*/
public String getName() {
return LaunchingMessages.StandardVMType_Standard_VM_3;
}
protected IVMInstall doCreateVMInstall(String id) {
return new StandardVM(this, id);
}
// /**
// * Return library information corresponding to the specified install
// * location. If the info does not exist, create it using the given Java
// * executable.
// */
// protected synchronized LibraryInfo getLibraryInfo(File javaHome, File javaExecutable) {
//
// // See if we already know the info for the requested VM. If not, generate it.
// String installPath = javaHome.getAbsolutePath();
// LibraryInfo info = LaunchingPlugin.getLibraryInfo(installPath);
// if (info == null) {
// info= (LibraryInfo)fgFailedInstallPath.get(installPath);
// if (info == null) {
// info = generateLibraryInfo(javaHome, javaExecutable);
// if (info == null) {
// info = getDefaultLibraryInfo(javaHome);
// fgFailedInstallPath.put(installPath, info);
// } else {
// // only persist if we were able to generate info - see bug 70011
// LaunchingPlugin.setLibraryInfo(installPath, info);
// }
// }
// }
// return info;
// }
//
// /**
// * Return <code>true</code> if the appropriate system libraries can be found for the
// * specified javascript executable, <code>false</code> otherwise.
// */
// protected boolean canDetectDefaultSystemLibraries(File javaHome, File javaExecutable) {
// LibraryLocation[] locations = getDefaultLibraryLocations(javaHome);
// String version = getVMVersion(javaHome, javaExecutable);
// return locations.length > 0 && !version.startsWith("1.1"); //$NON-NLS-1$
// }
/**
* Returns the version of the VM at the given location, with the given
* executable.
*
* @param javaHome
* @param javaExecutable
* @return String
*/
protected String getVMVersion(File javaHome, File javaExecutable) {
// LibraryInfo info = getLibraryInfo(javaHome, javaExecutable);
// return info.getVersion();
//TODO: implement
throw new org.eclipse.wst.jsdt.core.UnimplementedException();
}
/* (non-Javadoc)
* @see org.eclipse.jdt.launching.IVMInstallType#detectInstallLocation()
*/
public File detectInstallLocation() {
// // do not detect on the Mac OS
// if (Platform.getOS().equals(Constants.OS_MACOSX)) {
// return null;
// }
//
// // Retrieve the 'java.home' system property. If that directory doesn't exist,
// // return null.
// File javaHome;
// try {
// javaHome= new File (System.getProperty("java.home")).getCanonicalFile(); //$NON-NLS-1$
// } catch (IOException e) {
// LaunchingPlugin.log(e);
// return null;
// }
// if (!javaHome.exists()) {
// return null;
// }
//
// // Find the 'java' executable file under the javascript home directory. If it can't be
// // found, return null.
// File javaExecutable = findJavaExecutable(javaHome);
// if (javaExecutable == null) {
// return null;
// }
//
// // If the reported javascript home directory terminates with 'jre', first see if
// // the parent directory contains the required libraries
// boolean foundLibraries = false;
// if (javaHome.getName().equalsIgnoreCase("jre")) { //$NON-NLS-1$
// File parent= new File(javaHome.getParent());
// if (canDetectDefaultSystemLibraries(parent, javaExecutable)) {
// javaHome = parent;
// foundLibraries = true;
// }
// }
//
// // If we haven't already found the libraries, look in the reported javascript home dir
// if (!foundLibraries) {
// if (!canDetectDefaultSystemLibraries(javaHome, javaExecutable)) {
// return null;
// }
// }
//
// return javaHome;
//TODO: implement
throw new org.eclipse.wst.jsdt.core.UnimplementedException();
}
/**
* Return an <code>IPath</code> corresponding to the single library file containing the
* standard JavaScript classes for most VMs version 1.2 and above.
*/
protected IPath getDefaultSystemLibrary(File javaHome) {
IPath jreLibPath= new Path(javaHome.getPath()).append("lib").append("rt.jar"); //$NON-NLS-2$ //$NON-NLS-1$
if (jreLibPath.toFile().isFile()) {
return jreLibPath;
}
return new Path(javaHome.getPath()).append("jre").append("lib").append("rt.jar"); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
}
/**
* Returns a path to the source attachment for the given libaray, or
* an empty path if none.
*
* @param libLocation
* @return a path to the source attachment for the given library, or
* an empty path if none
*/
protected IPath getDefaultSystemLibrarySource(File libLocation) {
File parent= libLocation.getParentFile();
while (parent != null) {
File parentsrc= new File(parent, "src.jar"); //$NON-NLS-1$
if (parentsrc.isFile()) {
setDefaultRootPath("src");//$NON-NLS-1$
return new Path(parentsrc.getPath());
}
parentsrc= new File(parent, "src.zip"); //$NON-NLS-1$
if (parentsrc.isFile()) {
setDefaultRootPath(""); //$NON-NLS-1$
return new Path(parentsrc.getPath());
}
parent = parent.getParentFile();
}
// if we didn't find any of the normal source files, look for J9 source
IPath result = checkForJ9LibrarySource(libLocation);
if (result != null)
return result;
setDefaultRootPath(""); //$NON-NLS-1$
return Path.EMPTY;
}
// J9 has a known/fixed structure for its libs and source locations. Here just
// look for the source associated with each lib.
private IPath checkForJ9LibrarySource(File libLocation) {
File parent= libLocation.getParentFile();
String name = libLocation.getName();
if (name.equalsIgnoreCase("classes.zip")) { //$NON-NLS-1$
File source = new File(parent, "source/source.zip"); //$NON-NLS-1$
return source.isFile() ? new Path(source.getPath()) : Path.EMPTY;
}
if (name.equalsIgnoreCase("locale.zip")) { //$NON-NLS-1$
File source = new File(parent, "source/locale-src.zip"); //$NON-NLS-1$
return source.isFile() ? new Path(source.getPath()) : Path.EMPTY;
}
if (name.equalsIgnoreCase("charconv.zip")) { //$NON-NLS-1$
File source = new File(parent, "charconv-src.zip"); //$NON-NLS-1$
return source.isFile() ? new Path(source.getPath()) : Path.EMPTY;
}
return null;
}
protected IPath getDefaultPackageRootPath() {
return new Path(getDefaultRootPath());
}
/**
* NOTE: We do not add libraries from the "endorsed" directory explicitly, as
* the bootpath contains these entries already (if they exist).
*
* @see org.eclipse.jdt.launching.IVMInstallType#getDefaultLibraryLocations(File)
*/
public LibraryLocation[] getDefaultLibraryLocations(File installLocation) {
File libFile = new File(installLocation,"system.js"); //$NON-NLS-1$
Path libPath = new Path(libFile.getAbsolutePath());
LibraryLocation location = new LibraryLocation(libPath,null,null);
return new LibraryLocation[]{location};
// // Determine the javascript executable that corresponds to the specified install location
// // and use this to generate library info. If no javascript executable was found,
// // the 'standard' libraries will be returned.
// File javaExecutable = findJavaExecutable(installLocation);
// LibraryInfo libInfo;
// if (javaExecutable == null) {
// libInfo = getDefaultLibraryInfo(installLocation);
// } else {
// libInfo = getLibraryInfo(installLocation, javaExecutable);
// }
//
// String[] bootpath = libInfo.getBootpath();
//
// List endorsed = gatherAllLibraries(libInfo.getEndorsedDirs());
// List extensions = gatherAllLibraries(libInfo.getExtensionDirs());
// List allLibs = new ArrayList(endorsed.size() + bootpath.length + extensions.size());
//
// // Add all endorsed libraries - they are first, as they replace
// // classes in the standard libraries/bootpath
// appendLibraries(endorsed, allLibs);
//
// // next is the bootpath libraries
// List boot = new ArrayList(bootpath.length);
// URL url = getDefaultJavadocLocation(installLocation);
// for (int i = 0; i < bootpath.length; i++) {
// IPath path = new Path(bootpath[i]);
// File lib = path.toFile();
// if (lib.exists() && lib.isFile()) {
// LibraryLocation libraryLocation = new LibraryLocation(path,
// getDefaultSystemLibrarySource(lib),
// getDefaultPackageRootPath(),
// url);
// boot.add(libraryLocation);
// }
// }
// appendLibraries(boot, allLibs);
//
// // Add all extension libraries
// appendLibraries(extensions, allLibs);
//
// return (LibraryLocation[])allLibs.toArray(new LibraryLocation[allLibs.size()]);
}
/**
* Appends the non-duplicate libraries in libraryLocations to the list
* of allLibs.
*
* @param libraryLocations libraries to append
* @param allLibs list to append to, omitting duplicates
*/
// private void appendLibraries(List libraryLocations, List allLibs) {
// Iterator iter = libraryLocations.iterator();
// while (iter.hasNext()) {
// LibraryLocation lib = (LibraryLocation)iter.next();
// // check for dups, in case bootpath contains an ext dir entry (see bug 50201)
// if (!isDuplicateLibrary(allLibs, lib)) {
// allLibs.add(lib);
// }
// }
// }
/**
* Returns whether the given library is already contained in the given list.
* Rather than checking the library for equality (which considers source attachments),
* we check the actual OS path to the library for equality.
*
* @param libs list of library locations
* @param dup possible dup
* @return whether dup is contained in list of libraries
*/
// private boolean isDuplicateLibrary(List libs, LibraryLocation dup) {
// String osPath = dup.getSystemLibraryPath().toOSString();
// for (int i = 0; i < libs.size(); i++) {
// LibraryLocation location = (LibraryLocation) libs.get(i);
// if (location.getSystemLibraryPath().toOSString().equalsIgnoreCase(osPath)) {
// return true;
// }
// }
// return false;
// }
// /**
// * Returns default library info for the given install location.
// *
// * @param installLocation
// * @return LibraryInfo
// */
// protected LibraryInfo getDefaultLibraryInfo(File installLocation) {
// IPath rtjar = getDefaultSystemLibrary(installLocation);
// File extDir = getDefaultExtensionDirectory(installLocation);
// File endDir = getDefaultEndorsedDirectory(installLocation);
// String[] dirs = null;
// if (extDir == null) {
// dirs = new String[0];
// } else {
// dirs = new String[] {extDir.getAbsolutePath()};
// }
// String[] endDirs = null;
// if (endDir == null) {
// endDirs = new String[0];
// } else {
// endDirs = new String[] {endDir.getAbsolutePath()};
// }
// return new LibraryInfo("???", new String[] {rtjar.toOSString()}, dirs, endDirs); //$NON-NLS-1$
// }
/**
* Returns a list of all zips and jars contained in the given directories.
*
* @param dirPaths a list of absolute paths of directories to search
* @return List of all zips and jars
*/
protected List gatherAllLibraries(String[] dirPaths) {
List libraries = new ArrayList();
for (int i = 0; i < dirPaths.length; i++) {
File extDir = new File(dirPaths[i]);
if (extDir.exists() && extDir.isDirectory()) {
String[] names = extDir.list();
for (int j = 0; j < names.length; j++) {
String name = names[j];
File jar = new File(extDir, name);
if (jar.isFile()) {
int length = name.length();
if (length > 4) {
String suffix = name.substring(length - 4);
if (suffix.equalsIgnoreCase(".zip") || suffix.equalsIgnoreCase(".jar")) { //$NON-NLS-1$ //$NON-NLS-2$
try {
IPath libPath = new Path(jar.getCanonicalPath());
LibraryLocation library = new LibraryLocation(libPath, Path.EMPTY, Path.EMPTY, null);
libraries.add(library);
} catch (IOException e) {
Util.log(e, ""); //$NON-NLS-1$
}
}
}
}
}
}
}
return libraries;
}
/**
* Returns the default location of the extension directory, based on the given
* install location. The resulting file may not exist, or be <code>null</code>
* if an extension directory is not supported.
*
* @param installLocation
* @return default extension directory or <code>null</code>
*/
protected File getDefaultExtensionDirectory(File installLocation) {
File jre = null;
if (installLocation.getName().equalsIgnoreCase("jre")) { //$NON-NLS-1$
jre = installLocation;
} else {
jre = new File(installLocation, "jre"); //$NON-NLS-1$
}
File lib = new File(jre, "lib"); //$NON-NLS-1$
File ext = new File(lib, "ext"); //$NON-NLS-1$
return ext;
}
/**
* Returns the default location of the endorsed directory, based on the
* given install location. The resulting file may not exist, or be
* <code>null</code> if an endorsed directory is not supported.
*
* @param installLocation
* @return default endorsed directory or <code>null</code>
*/
protected File getDefaultEndorsedDirectory(File installLocation) {
File lib = new File(installLocation, "lib"); //$NON-NLS-1$
File ext = new File(lib, "endorsed"); //$NON-NLS-1$
return ext;
}
protected String getDefaultRootPath() {
return fDefaultRootPath;
}
protected void setDefaultRootPath(String defaultRootPath) {
fDefaultRootPath = defaultRootPath;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.launching.IVMInstallType#validateInstallLocation(java.io.File)
*/
public IStatus validateInstallLocation(File javaHome) {
// IStatus status = null;
// if (Platform.getOS().equals(Constants.OS_MACOSX)) {
// status = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), 0, LaunchingMessages.StandardVMType_Standard_VM_not_supported_on_MacOS__1, null);
// } else {
// File javaExecutable = findJavaExecutable(javaHome);
// if (javaExecutable == null) {
// status = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), 0, LaunchingMessages.StandardVMType_Not_a_JDK_Root__Java_executable_was_not_found_1, null); //
// } else {
// if (canDetectDefaultSystemLibraries(javaHome, javaExecutable)) {
// status = new Status(IStatus.OK, LaunchingPlugin.getUniqueIdentifier(), 0, LaunchingMessages.StandardVMType_ok_2, null);
// } else {
// status = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), 0, LaunchingMessages.StandardVMType_Not_a_JDK_root__System_library_was_not_found__1, null);
// }
// }
// }
// return status;
//TODO: implement
throw new org.eclipse.wst.jsdt.core.UnimplementedException();
}
// /**
// * Generates library information for the given javascript executable. A main
// * program is run (<code>org.eclipse.jdt.internal.launching.support.
// * LibraryDetector</code>), that dumps the system properties for bootpath
// * and extension directories. This output is then parsed and cached for
// * future reference.
// *
// * @return library info or <code>null</code> if none
// */
// protected LibraryInfo generateLibraryInfo(File javaHome, File javaExecutable) {
// LibraryInfo info = null;
//
// // if this is 1.1.X, the properties will not exist
// IPath classesZip = new Path(javaHome.getAbsolutePath()).append("lib").append("classes.zip"); //$NON-NLS-1$ //$NON-NLS-2$
// if (classesZip.toFile().exists()) {
// return new LibraryInfo("1.1.x", new String[] {classesZip.toOSString()}, new String[0], new String[0]); //$NON-NLS-1$
// }
// //locate the launching support jar - it contains the main program to run
// File file = LaunchingPlugin.getFileInPlugin(new Path("lib/launchingsupport.jar")); //$NON-NLS-1$
// if (file.exists()) {
// String javaExecutablePath = javaExecutable.getAbsolutePath();
// String[] cmdLine = new String[] {javaExecutablePath, "-includepath", file.getAbsolutePath(), "org.eclipse.jdt.internal.launching.support.LibraryDetector"}; //$NON-NLS-1$ //$NON-NLS-2$
// Process p = null;
// try {
// p = Runtime.getRuntime().exec(cmdLine);
// IProcess process = DebugPlugin.newProcess(new Launch(null, ILaunchManager.RUN_MODE, null), p, "Library Detection"); //$NON-NLS-1$
// for (int i= 0; i < 200; i++) {
// // Wait no more than 10 seconds (200 * 50 mils)
// if (process.isTerminated()) {
// break;
// }
// try {
// Thread.sleep(50);
// } catch (InterruptedException e) {
// }
// }
// info = parseLibraryInfo(process);
// } catch (IOException ioe) {
// LaunchingPlugin.log(ioe);
// } finally {
// if (p != null) {
// p.destroy();
// }
// }
// }
// if (info == null) {
// // log error that we were unable to generate library info - see bug 70011
// LaunchingPlugin.log(MessageFormat.format("Failed to retrieve default libraries for {0}", new String[]{javaHome.getAbsolutePath()})); //$NON-NLS-1$
// }
// return info;
// }
//
// /**
// * Parses the output from 'LibraryDetector'.
// */
// protected LibraryInfo parseLibraryInfo(IProcess process) {
// IStreamsProxy streamsProxy = process.getStreamsProxy();
// String text = null;
// if (streamsProxy != null) {
// text = streamsProxy.getOutputStreamMonitor().getContents();
// }
// if (text != null && text.length() > 0) {
// int index = text.indexOf("|"); //$NON-NLS-1$
// if (index > 0) {
// String version = text.substring(0, index);
// text = text.substring(index + 1);
// index = text.indexOf("|"); //$NON-NLS-1$
// if (index > 0) {
// String bootPaths = text.substring(0, index);
// String[] bootPath = parsePaths(bootPaths);
//
// text = text.substring(index + 1);
// index = text.indexOf("|"); //$NON-NLS-1$
//
// if (index > 0) {
// String extDirPaths = text.substring(0, index);
// String endorsedDirsPath = text.substring(index + 1);
// String[] extDirs = parsePaths(extDirPaths);
// String[] endDirs = parsePaths(endorsedDirsPath);
// return new LibraryInfo(version, bootPath, extDirs, endDirs);
// }
// }
// }
// }
// return null;
// }
protected String[] parsePaths(String paths) {
List list = new ArrayList();
int pos = 0;
int index = paths.indexOf(File.pathSeparatorChar, pos);
while (index > 0) {
String path = paths.substring(pos, index);
list.add(path);
pos = index + 1;
index = paths.indexOf(File.pathSeparatorChar, pos);
}
String path = paths.substring(pos);
if (!path.equals("null")) { //$NON-NLS-1$
list.add(path);
}
return (String[])list.toArray(new String[list.size()]);
}
/* (non-Javadoc)
* @see org.eclipse.jdt.launching.IVMInstallType#disposeVMInstall(java.lang.String)
*/
public void disposeVMInstall(String id) {
IVMInstall vm = findVMInstall(id);
if (vm != null) {
// String path = vm.getInstallLocation().getAbsolutePath();
// LaunchingPlugin.setLibraryInfo(path, null);
// fgFailedInstallPath.remove(path);
//TODO: implement
throw new org.eclipse.wst.jsdt.core.UnimplementedException();
}
super.disposeVMInstall(id);
}
/* (non-Javadoc)
* @see org.eclipse.jdt.launching.AbstractVMInstallType#getDefaultJavadocLocation(java.io.File)
*/
public URL getDefaultJavadocLocation(File installLocation) {
// File javaExecutable = findJavaExecutable(installLocation);
// if (javaExecutable != null) {
// LibraryInfo libInfo = getLibraryInfo(installLocation, javaExecutable);
// if (libInfo != null) {
// String version = libInfo.getVersion();
// if (version != null) {
// try {
// if (version.startsWith("1.5")) { //$NON-NLS-1$
// return new URL("http://java.sun.com/j2se/1.5.0/docs/api/"); //$NON-NLS-1$
// } else if (version.startsWith("1.4")) { //$NON-NLS-1$
// return new URL("http://java.sun.com/j2se/1.4.2/docs/api/"); //$NON-NLS-1$
// } else if (version.startsWith("1.3")) { //$NON-NLS-1$
// return new URL("http://java.sun.com/j2se/1.3/docs/api/"); //$NON-NLS-1$
// } else if (version.startsWith("1.2")) { //$NON-NLS-1$
// return new URL("http://java.sun.com/products/jdk/1.2/docs/api"); //$NON-NLS-1$
// }
// } catch (MalformedURLException e) {
// }
// }
// }
// }
// return null;
//TODO: implement
throw new org.eclipse.wst.jsdt.core.UnimplementedException();
}
}