blob: 40ff2d46ea845c6021a7f1c7dfb98b4a02f79e11 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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.jdt.internal.launching;
import java.io.File;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.jdt.launching.AbstractVMRunner;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.VMRunnerConfiguration;
public class StandardVMRunner extends AbstractVMRunner {
protected IVMInstall fVMInstance;
public StandardVMRunner(IVMInstall vmInstance) {
fVMInstance= vmInstance;
}
protected String renderDebugTarget(String classToRun, int host) {
String format= LaunchingMessages.StandardVMRunner__0__at_localhost__1__1;
return MessageFormat.format(format, new String[] { classToRun, String.valueOf(host) });
}
public static String renderProcessLabel(String[] commandLine) {
String format= LaunchingMessages.StandardVMRunner__0____1___2;
String timestamp= DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).format(new Date(System.currentTimeMillis()));
return MessageFormat.format(format, new String[] { commandLine[0], timestamp });
}
protected static String renderCommandLine(String[] commandLine) {
if (commandLine.length < 1)
return ""; //$NON-NLS-1$
StringBuffer buf= new StringBuffer();
for (int i= 0; i < commandLine.length; i++) {
buf.append(' ');
char[] characters= commandLine[i].toCharArray();
StringBuffer command= new StringBuffer();
boolean containsSpace= false;
for (int j = 0; j < characters.length; j++) {
char character= characters[j];
if (character == '\"') {
command.append('\\');
} else if (character == ' ') {
containsSpace = true;
}
command.append(character);
}
if (containsSpace) {
buf.append('\"');
buf.append(command.toString());
buf.append('\"');
} else {
buf.append(command.toString());
}
}
return buf.toString();
}
protected void addArguments(String[] args, List v) {
if (args == null) {
return;
}
for (int i= 0; i < args.length; i++) {
v.add(args[i]);
}
}
/**
* Returns the working directory to use for the launched VM,
* or <code>null</code> if the working directory is to be inherited
* from the current process.
*
* @return the working directory to use
* @exception CoreException if the working directory specified by
* the configuration does not exist or is not a directory
*/
protected File getWorkingDir(VMRunnerConfiguration config) throws CoreException {
String path = config.getWorkingDirectory();
if (path == null) {
return null;
}
File dir = new File(path);
if (!dir.isDirectory()) {
abort(MessageFormat.format(LaunchingMessages.StandardVMRunner_Specified_working_directory_does_not_exist_or_is_not_a_directory___0__3, new String[] {path}), null, IJavaLaunchConfigurationConstants.ERR_WORKING_DIRECTORY_DOES_NOT_EXIST);
}
return dir;
}
/**
* @see VMRunner#getPluginIdentifier()
*/
protected String getPluginIdentifier() {
return LaunchingPlugin.getUniqueIdentifier();
}
/**
* Construct and return a String containing the full path of a java executable
* command such as 'java' or 'javaw.exe'. If the configuration specifies an
* explicit executable, that is used.
*
* @return full path to java executable
* @exception CoreException if unable to locate an executeable
*/
protected String constructProgramString(VMRunnerConfiguration config) throws CoreException {
// Look for the user-specified java executable command
String command= null;
Map map= config.getVMSpecificAttributesMap();
if (map != null) {
command = (String)map.get(IJavaLaunchConfigurationConstants.ATTR_JAVA_COMMAND);
}
// If no java command was specified, use default executable
if (command == null) {
File exe = StandardVMType.findJavaExecutable(fVMInstance.getInstallLocation());
if (exe == null) {
abort(MessageFormat.format(LaunchingMessages.StandardVMRunner_Unable_to_locate_executable_for__0__1, new String[]{fVMInstance.getName()}), null, IJavaLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
}
return exe.getAbsolutePath();
}
// Build the path to the java executable. First try 'bin', and if that
// doesn't exist, try 'jre/bin'
String installLocation = fVMInstance.getInstallLocation().getAbsolutePath() + File.separatorChar;
File exe = new File(installLocation + "bin" + File.separatorChar + command); //$NON-NLS-1$
if (fileExists(exe)){
return exe.getAbsolutePath();
}
exe = new File(exe.getAbsolutePath() + ".exe"); //$NON-NLS-1$
if (fileExists(exe)){
return exe.getAbsolutePath();
}
exe = new File(installLocation + "jre" + File.separatorChar + "bin" + File.separatorChar + command); //$NON-NLS-1$ //$NON-NLS-2$
if (fileExists(exe)) {
return exe.getAbsolutePath();
}
exe = new File(exe.getAbsolutePath() + ".exe"); //$NON-NLS-1$
if (fileExists(exe)) {
return exe.getAbsolutePath();
}
// not found
abort(MessageFormat.format(LaunchingMessages.StandardVMRunner_Specified_executable__0__does_not_exist_for__1__4, new String[]{command, fVMInstance.getName()}), null, IJavaLaunchConfigurationConstants.ERR_INTERNAL_ERROR);
// NOTE: an exception will be thrown - null cannot be returned
return null;
}
protected boolean fileExists(File file) {
return file.exists() && file.isFile();
}
protected String convertClassPath(String[] cp) {
int pathCount= 0;
StringBuffer buf= new StringBuffer();
if (cp.length == 0) {
return ""; //$NON-NLS-1$
}
for (int i= 0; i < cp.length; i++) {
if (pathCount > 0) {
buf.append(File.pathSeparator);
}
buf.append(cp[i]);
pathCount++;
}
return buf.toString();
}
/* (non-Javadoc)
* @see org.eclipse.jdt.launching.IVMRunner#run(org.eclipse.jdt.launching.VMRunnerConfiguration, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
*/
public void run(VMRunnerConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
IProgressMonitor subMonitor = new SubProgressMonitor(monitor, 1);
subMonitor.beginTask(LaunchingMessages.StandardVMRunner_Launching_VM____1, 2);
subMonitor.subTask(LaunchingMessages.StandardVMRunner_Constructing_command_line____2);
String program= constructProgramString(config);
List arguments= new ArrayList();
arguments.add(program);
// VM args are the first thing after the java program so that users can specify
// options like '-client' & '-server' which are required to be the first option
String[] allVMArgs = combineVmArgs(config, fVMInstance);
addArguments(allVMArgs, arguments);
addBootClassPathArguments(arguments, config);
String[] cp= config.getClassPath();
if (cp.length > 0) {
arguments.add("-classpath"); //$NON-NLS-1$
arguments.add(convertClassPath(cp));
}
arguments.add(config.getClassToLaunch());
String[] programArgs= config.getProgramArguments();
addArguments(programArgs, arguments);
String[] cmdLine= new String[arguments.size()];
arguments.toArray(cmdLine);
String[] envp= config.getEnvironment();
subMonitor.worked(1);
// check for cancellation
if (monitor.isCanceled()) {
return;
}
subMonitor.subTask(LaunchingMessages.StandardVMRunner_Starting_virtual_machine____3);
Process p= null;
File workingDir = getWorkingDir(config);
p= exec(cmdLine, workingDir, envp);
if (p == null) {
return;
}
// check for cancellation
if (monitor.isCanceled()) {
p.destroy();
return;
}
IProcess process= newProcess(launch, p, renderProcessLabel(cmdLine), getDefaultProcessMap());
process.setAttribute(IProcess.ATTR_CMDLINE, renderCommandLine(cmdLine));
subMonitor.worked(1);
subMonitor.done();
}
protected void addBootClassPathArguments(List arguments, VMRunnerConfiguration config) {
String[] prependBootCP= null;
String[] bootCP= null;
String[] appendBootCP= null;
Map map = config.getVMSpecificAttributesMap();
if (map != null) {
prependBootCP= (String[]) map.get(IJavaLaunchConfigurationConstants.ATTR_BOOTPATH_PREPEND);
bootCP= (String[]) map.get(IJavaLaunchConfigurationConstants.ATTR_BOOTPATH);
appendBootCP= (String[]) map.get(IJavaLaunchConfigurationConstants.ATTR_BOOTPATH_APPEND);
}
if (prependBootCP == null && bootCP == null && appendBootCP == null) {
// use old single attribute instead of new attributes if not specified
bootCP = config.getBootClassPath();
}
if (prependBootCP != null) {
arguments.add("-Xbootclasspath/p:" + convertClassPath(prependBootCP)); //$NON-NLS-1$
}
if (bootCP != null) {
if (bootCP.length > 0) {
arguments.add("-Xbootclasspath:" + convertClassPath(bootCP)); //$NON-NLS-1$
}
}
if (appendBootCP != null) {
arguments.add("-Xbootclasspath/a:" + convertClassPath(appendBootCP)); //$NON-NLS-1$
}
}
}