001 /*BEGIN_COPYRIGHT_BLOCK 002 * 003 * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/ 004 * or http://sourceforge.net/projects/drjava/ 005 * 006 * DrJava Open Source License 007 * 008 * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved. 009 * 010 * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/ 011 * 012 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 013 * documentation files (the "Software"), to deal with the Software without restriction, including without limitation 014 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 015 * to permit persons to whom the Software is furnished to do so, subject to the following conditions: 016 * 017 * - Redistributions of source code must retain the above copyright notice, this list of conditions and the 018 * following disclaimers. 019 * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 020 * following disclaimers in the documentation and/or other materials provided with the distribution. 021 * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to 022 * endorse or promote products derived from this Software without specific prior written permission. 023 * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their 024 * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu. 025 * 026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 027 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN_EQ NO EVENT SHALL THE 028 * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN_EQ AN ACTION OF 029 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT_EQ OF OR IN_EQ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 030 * WITH THE SOFTWARE. 031 * 032 END_COPYRIGHT_BLOCK*/ 033 034 package edu.rice.cs.cunit.util; 035 036 import java.io.File; 037 import java.io.IOException; 038 import java.util.LinkedList; 039 import java.util.Locale; 040 041 /** A utility class to allow executing another JVM. 042 * @version $Id: ExecJVM.java 3928 2006-08-01 19:18:36Z rcartwright $ 043 */ 044 public final class ExecJVM { 045 private static final String PATH_SEPARATOR = System.getProperty("path.separator"); 046 private static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.US); 047 048 private ExecJVM() { } 049 050 /** Runs a new JVM. 051 * @param mainClass Class to run 052 * @param classParams Parameters to pass to the main class 053 * @param classPath Array of items to put in classpath of new JVM 054 * @param jvmParams Array of additional command-line parameters to pass to JVM 055 * @param workDir working directory 056 * @return {@link Process} object corresponding to the executed JVM 057 * @throws IOException 058 */ 059 public static Process runJVM(String mainClass, String[] classParams, String[] classPath, String[] jvmParams, File workDir) 060 throws IOException { 061 062 final StringBuilder buf = new StringBuilder(); 063 for (int i = 0; i < classPath.length; i++) { 064 if (i != 0) buf.append(PATH_SEPARATOR); 065 066 buf.append(classPath[i]); 067 } 068 069 return runJVM(mainClass, classParams, buf.toString(), jvmParams, workDir); 070 } 071 072 /** Runs a new JVM. 073 * @param mainClass Class to run 074 * @param classParams Parameters to pass to the main class 075 * @param classPath Pre-formatted classpath parameter 076 * @param jvmParams Array of additional command-line parameters to pass to JVM 077 * @param workDir working directory 078 * @return {@link Process} object corresponding to the executed JVM 079 * @throws IOException 080 */ 081 public static Process runJVM(String mainClass, String[] classParams, String classPath, String[] jvmParams, File workDir) 082 throws IOException { 083 084 LinkedList<String> args = new LinkedList<String>(); 085 args.add("-classpath"); 086 args.add(edu.rice.cs.cunit.util.FileOps.convertToAbsolutePathEntries(classPath)); 087 _addArray(args, jvmParams); 088 String[] jvmWithCP = args.toArray(new String[args.size()]); 089 090 return _runJVM(mainClass, classParams, jvmWithCP, workDir); 091 } 092 093 /** Runs a new JVM, propagating the present classpath. It changes the entries in the class path to absolute form. 094 * @param mainClass Class to run 095 * @param classParams Parameters to pass to the main class 096 * @param jvmParams Array of additional command-line parameters to pass to JVM 097 * @param workDir working directory 098 * @return {@link Process} object corresponding to the executed JVM 099 * @throws IOException 100 */ 101 public static Process runJVMPropagateClassPath(String mainClass, String[] classParams, String[] jvmParams, File workDir) 102 throws IOException { 103 String cp = System.getProperty("java.class.path"); 104 return runJVM(mainClass, classParams, cp, jvmParams, workDir); 105 } 106 107 /** Runs a new JVM, propagating the present classpath. 108 * @param mainClass Class to run 109 * @param classParams Parameters to pass to the main class 110 * @param workDir working directory 111 * @return {@link Process} object corresponding to the new JVM process 112 * @throws IOException 113 */ 114 public static Process runJVMPropagateClassPath(String mainClass, String[] classParams, File workDir) 115 throws IOException { 116 return runJVMPropagateClassPath(mainClass, classParams, new String[0], workDir); 117 } 118 119 /** Creates and runs a new JVM. This method is private now because it cannot change the classpath entries to 120 * absolute paths, so it should not be used. 121 * 122 * @param mainClass Class to run 123 * @param classParams Parameters to pass to the main class 124 * @param jvmParams Array of additional command-line parameters to pass to JVM 125 * @param workDir working directory 126 * 127 * @return {@link Process} object corresponding to the executed JVM 128 * 129 * @throws IOException 130 */ 131 private static Process _runJVM(String mainClass, String[] classParams, String[] jvmParams, File workDir) throws IOException { 132 LinkedList<String> args = new LinkedList<String>(); 133 args.add(_getExecutable()); 134 _addArray(args, jvmParams); 135 args.add(mainClass); 136 _addArray(args, classParams); 137 138 String[] argArray = args.toArray(new String[args.size()]); 139 140 // exec our "java" command in the specified working directory setting 141 Process p; 142 if (workDir != null) { 143 // execute in the working directory 144 if (workDir.exists()) { 145 p = Runtime.getRuntime().exec(argArray, null, workDir); 146 } 147 else { 148 p = Runtime.getRuntime().exec(argArray); 149 } 150 } 151 else { 152 // execute without caring about working directory 153 p = Runtime.getRuntime().exec(argArray); 154 } 155 return p; 156 } 157 158 159 private static void _addArray(LinkedList<String> list, String[] array) { 160 if (array != null) { 161 for (int i = 0; i < array.length; i++) { 162 list.add(array[i]); 163 } 164 } 165 } 166 167 168 /** DOS/Windows family OS's use ; to separate paths. 169 * @return true if DOS/Windows */ 170 private static boolean _isDOS() { 171 return PATH_SEPARATOR.equals(";"); 172 } 173 174 /** @return true if Netware */ 175 private static boolean _isNetware() { 176 return OS_NAME.indexOf("netware") != -1; 177 } 178 179 /** 180 * Find the java executable. 181 * This logic comes from Ant. 182 * @return java executable string 183 */ 184 private static String _getExecutable() { 185 // this netware thing is based on comments from ant's code 186 if (_isNetware()) return "java"; 187 188 File executable; 189 190 String java_home = System.getProperty("java.home") + "/"; 191 192 String[] candidates = { java_home + "../bin/java", java_home + "bin/java", java_home + "java", }; 193 194 // search all the candidates to find java 195 for (int i = 0; i < candidates.length; i++) { 196 String current = candidates[i]; 197 198 // try javaw.exe first for dos, otherwise try java.exe for dos 199 if (_isDOS()) { 200 executable = new File(current + "w.exe"); 201 if (! executable.exists()) executable = new File(current + ".exe"); 202 } 203 else executable = new File(current); 204 205 //System.err.println("checking: " + executable); 206 207 if (executable.exists()) { 208 //System.err.println("JVM executable found: " + executable.getAbsolutePath()); 209 return executable.getAbsolutePath(); 210 } 211 } 212 213 // hope for the best using the system's path! 214 //System.err.println("Could not find java executable, using 'java'!"); 215 return "java"; 216 } 217 } 218