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