| /******************************************************************************* |
| * 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.core.tests.runtime; |
| |
| import java.io.*; |
| |
| import java.util.Vector; |
| |
| import org.eclipse.wst.jsdt.core.tests.util.Util; |
| |
| /** |
| * A J9 VM launcher launches an external J9 VM (and J9 Proxy if needed) with |
| * the given arguments on the same machine. |
| * <p> |
| * Unlike with the <code>StandardVMLauncher</code>, a debugger would have to |
| * connect to the J9 Proxy instead of connecting to the VM directly. In this case, |
| * the Proxy port is the specified debug port. Note that an internal debug port |
| * must also be specified. This port is used for the communication between the |
| * Proxy and the VM. |
| */ |
| public class J9VMLauncher extends LocalVMLauncher implements RuntimeConstants { |
| int internalDebugPort = -1; |
| String proxyOutFile; |
| String symbolPath; |
| /** |
| * Creates a new J9VMLauncher that launches a J9 VM |
| * (and J9 Proxy if needed) on the same machine. |
| */ |
| public J9VMLauncher() { |
| super(); |
| } |
| /** |
| * Builds the actual boot class path that is going to be passed to the VM. |
| */ |
| protected String buildBootClassPath() { |
| StringBuffer bootPathString = new StringBuffer(); |
| char pathSeparator = File.pathSeparatorChar; |
| |
| if (this.bootPath != null) { |
| // Add boot class path given by client |
| int length = this.bootPath.length; |
| for (int i = 0; i < length; i++){ |
| bootPathString.append(this.bootPath[i]); |
| bootPathString.append(pathSeparator); |
| } |
| } else { |
| // Add regular classes.zip |
| bootPathString.append(this.vmPath); |
| bootPathString.append(File.separator); |
| bootPathString.append("lib"); |
| bootPathString.append(File.separator); |
| bootPathString.append("jclMax"); |
| bootPathString.append(File.separator); |
| bootPathString.append("classes.zip"); |
| bootPathString.append(pathSeparator); |
| } |
| |
| // Add boot class path directory if needed |
| if (this.evalTargetPath != null && TARGET_HAS_FILE_SYSTEM) { |
| bootPathString.append(this.evalTargetPath); |
| bootPathString.append(File.separatorChar); |
| bootPathString.append(BOOT_CLASSPATH_DIRECTORY); |
| } |
| |
| return bootPathString.toString(); |
| } |
| /** |
| * @see LocalVMLauncher#execCommandLine |
| */ |
| protected Process execCommandLine() throws TargetException { |
| // Check that the internal debug port has been specified if in debug mode |
| if (this.debugPort != -1 && this.internalDebugPort == -1) { |
| throw new TargetException("Internal debug port has not been specified"); |
| } |
| |
| return super.execCommandLine(); |
| } |
| /** |
| * @see LocalVMLauncher#getCommandLine |
| */ |
| public String[] getCommandLine() { |
| Vector commandLine = new Vector(); |
| |
| // VM binary |
| commandLine.addElement( |
| this.vmPath + |
| (this.vmPath.endsWith(File.separator) ? "" : File.separator) + |
| "bin" + |
| File.separator + |
| "j9"); |
| |
| // VM arguments |
| if (this.vmArguments != null) { |
| for (int i = 0; i < this.vmArguments.length; i++) { |
| commandLine.addElement(this.vmArguments[i]); |
| } |
| } |
| |
| // debug mode |
| if (this.debugPort != -1 && this.internalDebugPort != -1) { |
| commandLine.addElement("-debug:" + this.internalDebugPort); |
| } |
| |
| // boot class path |
| commandLine.addElement("-Xbootclasspath:" + buildBootClassPath()); |
| |
| // regular class path |
| commandLine.addElement("-classpath"); |
| commandLine.addElement(buildClassPath()); |
| |
| // code snippet runner class |
| if (this.evalPort != -1) { |
| commandLine.addElement(CODE_SNIPPET_RUNNER_CLASS_NAME); |
| } |
| |
| // code snippet runner arguments |
| if (this.evalPort != -1) { |
| commandLine.addElement(EVALPORT_ARG); |
| commandLine.addElement(Integer.toString(this.evalPort)); |
| if (TARGET_HAS_FILE_SYSTEM) { |
| commandLine.addElement(CODESNIPPET_CLASSPATH_ARG); |
| commandLine.addElement(this.evalTargetPath + File.separator + REGULAR_CLASSPATH_DIRECTORY); |
| commandLine.addElement(CODESNIPPET_BOOTPATH_ARG); |
| commandLine.addElement(this.evalTargetPath + File.separator + BOOT_CLASSPATH_DIRECTORY); |
| } |
| } |
| |
| // program class |
| if (this.programClass != null) { |
| commandLine.addElement(this.programClass); |
| } |
| |
| // program arguments |
| if (this.programArguments != null) { |
| for (int i=0;i<this.programArguments.length;i++) { |
| commandLine.addElement(this.programArguments[i]); |
| } |
| } |
| |
| String[] result= new String[commandLine.size()]; |
| commandLine.copyInto(result); |
| |
| // check for spaces in result |
| for (int i = 0; i < result.length; i++) { |
| String argument = result[i]; |
| if (argument.indexOf(' ') != -1) { |
| result[i] = "\"" + argument + "\""; |
| } |
| } |
| |
| return result; |
| } |
| /** |
| * Returns the debug port the J9 Proxy uses to connect to the J9 VM. |
| * The value is unspecified if debug mode is disabled. |
| * Note that the regular debug port is the port used to connect the J9 Proxy and |
| * the IDE in the case of the J9 VM Launcher. |
| */ |
| public int getInternalDebugPort() { |
| return this.internalDebugPort; |
| } |
| /** |
| * Returns the command line which will be used to launch the Proxy. |
| */ |
| public String[] getProxyCommandLine() { |
| Vector commandLine = new Vector(); |
| |
| // Proxy binary |
| commandLine.addElement( |
| this.vmPath + |
| (this.vmPath.endsWith(File.separator) ? "" : File.separator) + |
| "bin" + |
| File.separator + |
| "j9proxy"); |
| |
| // Arguments |
| commandLine.addElement(getTargetAddress() + ":" + this.internalDebugPort); |
| commandLine.addElement(Integer.toString(this.debugPort)); |
| if (this.symbolPath != null && this.symbolPath != "") { |
| commandLine.addElement(this.symbolPath); |
| } |
| |
| String[] result= new String[commandLine.size()]; |
| commandLine.copyInto(result); |
| return result; |
| } |
| /** |
| * Returns the full path name to the file where the proxy output is redirected. |
| * Returns "con" if the proxy output is redirected to the stdout. |
| * Returns null if the proxy output is not redirected. |
| */ |
| public String getProxyOutFile() { |
| return this.proxyOutFile; |
| } |
| /** |
| * Returns the full path name to the symbol file used by the J9 Proxy. |
| * Returns null if the no symbol file is passed to the J9 Proxy. |
| */ |
| public String getSymbolPath() { |
| return this.symbolPath; |
| } |
| /** |
| * @see LocalVMLauncher#launch |
| */ |
| public LocalVirtualMachine launch() throws TargetException { |
| // Launch VM |
| LocalVirtualMachine localVM = super.launch(); |
| |
| // Launch Proxy if needed |
| Process proxyProcess= null; |
| if (this.debugPort != -1) { |
| try { |
| // Use Runtime.exec(String[]) with tokens because Runtime.exec(String) with commandLineString |
| // does not properly handle spaces in arguments on Unix/Linux platforms. |
| String[] commandLine = getProxyCommandLine(); |
| |
| // DEBUG |
| /* |
| for (int i = 0; i < commandLine.length; i++) { |
| System.out.print(commandLine[i] + " "); |
| } |
| System.out.println(); |
| */ |
| |
| proxyProcess= Runtime.getRuntime().exec(commandLine); |
| } catch (IOException e) { |
| localVM.shutDown(); |
| throw new TargetException("Error launching J9 Proxy at " + this.vmPath); |
| } |
| } |
| |
| // Transform launched VM into J9 VM |
| Process vmProcess = localVM.process; |
| this.runningVMs.removeElement(localVM); |
| J9VirtualMachine vm= new J9VirtualMachine(vmProcess, this.debugPort, this.evalTargetPath, proxyProcess, this.proxyOutFile); |
| this.runningVMs.addElement(vm); |
| return vm; |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.wst.jsdt.core.tests.runtime.LocalVMLauncher#setDebugPort(int) |
| */ |
| public void setDebugPort(int debugPort) { |
| super.setDebugPort(debugPort); |
| |
| // specify default internal debug port as well |
| this.setInternalDebugPort(Util.getFreePort()); |
| } |
| |
| /** |
| * Sets the debug port the J9 Proxy uses to connect to the J9 VM. |
| * This is mandatory if debug mode is enabled. |
| * This is ignored if debug mode is disabled. |
| * Note that the regular debug port is the port used to connect the J9 Proxy and |
| * the IDE in the case of the J9 VM Launcher. |
| */ |
| public void setInternalDebugPort(int internalDebugPort) { |
| this.internalDebugPort = internalDebugPort; |
| } |
| /** |
| * Sets the full path name to the file where the proxy output must be redirected. |
| * Specify "con" if the proxy output must be redirected to the stdout. |
| * Specify null if the proxy output must not be redirected (default value). |
| * This is ignored if debug mode is disabled. |
| */ |
| public void setProxyOutFile(String proxyOutFile) { |
| this.proxyOutFile = proxyOutFile; |
| } |
| /** |
| * Sets the full path name to the symbol file used by the J9 Proxy. |
| * Specify null if the no symbol file must be passed to the J9 Proxy (default value). |
| * This is ignored if debug mode is disabled. |
| */ |
| public void setSymbolPath(String symbolPath) { |
| this.symbolPath = symbolPath; |
| } |
| } |