1 4 package com.tc.process; 5 6 import com.tc.util.Assert; 7 import com.tc.util.runtime.Os; 8 9 import java.io.File ; 10 import java.io.IOException ; 11 import java.io.InputStream ; 12 import java.io.OutputStream ; 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.Collections ; 16 import java.util.HashMap ; 17 import java.util.Iterator ; 18 import java.util.LinkedList ; 19 import java.util.List ; 20 import java.util.Map ; 21 22 36 public class LinkedJavaProcess { 37 38 private final String mainClassName; 39 private String [] javaArguments; 40 private final String [] arguments; 41 private String [] environment; 42 private File directory; 43 private File javaExecutable; 44 private boolean isDSO = false; 45 46 private Process process; 47 private boolean running; 48 private final List copiers = Collections.synchronizedList(new ArrayList ()); 49 50 public LinkedJavaProcess(String mainClassName, String [] classArguments) { 51 Assert.assertNotBlank(mainClassName); 52 53 if (classArguments == null) classArguments = new String [0]; 54 55 this.mainClassName = mainClassName; 56 this.javaArguments = null; 57 this.arguments = classArguments; 58 this.environment = null; 59 this.directory = null; 60 this.javaExecutable = null; 61 this.process = null; 62 this.running = false; 63 } 64 65 public LinkedJavaProcess(String mainClassName) { 66 this(mainClassName, null); 67 } 68 69 public void setJavaExecutable(File javaExecutable) { 70 Assert.assertNotNull(javaExecutable); 71 72 this.javaExecutable = javaExecutable; 73 } 74 75 public void setJavaArguments(String [] javaArguments) { 76 this.javaArguments = javaArguments; 77 } 78 79 public void setEnvironment(String [] environment) { 80 this.environment = environment; 81 } 82 83 public void setDirectory(File directory) { 84 this.directory = directory; 85 } 86 87 public void setDSOTarget(boolean isDSO) { 88 this.isDSO = isDSO; 89 } 90 91 public synchronized void destroy() { 92 if (!this.running) throw new IllegalStateException ("This LinkedJavaProcess is not running."); 93 this.process.destroy(); 94 this.running = false; 95 } 96 97 private synchronized void setJavaExecutableIfNecessary() throws IOException { 98 if (this.javaExecutable == null) { 99 File javaHome = new File (System.getProperty("java.home")); 100 File javaBin = new File (javaHome, "bin"); 101 File javaPlain = new File (javaBin, "java"); 102 File javaExe = new File (javaBin, "java.exe"); 103 104 if (this.javaExecutable == null) { 105 if (javaPlain.exists() && javaPlain.isFile()) this.javaExecutable = javaPlain; 106 } 107 108 if (this.javaExecutable == null) { 109 if (javaExe.exists() && javaExe.isFile()) this.javaExecutable = javaExe; 110 } 111 112 if (this.javaExecutable == null) { 113 throw new IOException ("Can't find the Java binary; perhaps you need to set it yourself? Tried " 115 + javaPlain.getAbsolutePath() + " and " + javaExe.getAbsolutePath()); 116 } 117 } 118 } 119 120 public synchronized void start() throws IOException { 121 if (this.running) throw new IllegalStateException ("This LinkedJavaProcess is already running."); 122 123 LinkedJavaProcessPollingAgent.startHeartBeatServer(); 124 125 List fullCommandList = new LinkedList (); 126 List allJavaArguments = new ArrayList (); 127 128 allJavaArguments.add("-Djava.class.path=" + System.getProperty("java.class.path")); 129 if (this.javaArguments != null) allJavaArguments.addAll(Arrays.asList(this.javaArguments)); 130 131 setJavaExecutableIfNecessary(); 132 133 int socketPort = LinkedJavaProcessPollingAgent.getChildProcessHeartbeatServerPort(); 134 135 Map env = makeEnvMap(Arrays.asList(this.environment == null ? new String [] {} : this.environment)); 136 fixupEnvironment(env); 137 138 fullCommandList.add(this.javaExecutable.getAbsolutePath()); 139 fullCommandList.addAll(allJavaArguments); 140 fullCommandList.add(isDSO ? DSOLinkedJavaProcessStarter.class.getName() : LinkedJavaProcessStarter.class.getName()); 141 fullCommandList.add(Integer.toString(socketPort)); 142 fullCommandList.add(this.mainClassName); 143 if (this.arguments != null) fullCommandList.addAll(Arrays.asList(this.arguments)); 144 145 String [] fullCommand = (String []) fullCommandList.toArray(new String [fullCommandList.size()]); 146 147 this.process = Runtime.getRuntime().exec(fullCommand, makeEnv(env), this.directory); 148 this.running = true; 149 } 150 151 private Map makeEnvMap(List list) { 152 Map rv = new HashMap (); 153 154 for (Iterator iter = list.iterator(); iter.hasNext();) { 155 String [] nameValue = ((String ) iter.next()).split("=", 2); 156 rv.put(nameValue[0], nameValue[1]); 157 } 158 159 return rv; 160 } 161 162 private String [] makeEnv(Map env) { 163 int i = 0; 164 String [] rv = new String [env.size()]; 165 for (Iterator iter = env.keySet().iterator(); iter.hasNext(); i++) { 166 String key = (String ) iter.next(); 167 rv[i] = key + "=" + env.get(key); 168 } 169 return rv; 170 } 171 172 private static void fixupEnvironment(Map env) { 173 if (Os.isWindows()) { 174 179 if (!env.containsKey("SYSTEMROOT")) { 180 String root = Os.findWindowsSystemRoot(); 181 if (root == null) { throw new RuntimeException ("cannot find %SYSTEMROOT% in the environment"); } 182 env.put("SYSTEMROOT", root); 183 } 184 185 String crappleDirs = "C:\\Program Files\\Rendezvous\\" + File.pathSeparator + "C:\\Program Files\\Bonjour\\"; 186 187 if (!env.containsKey("PATH")) { 188 env.put("PATH", crappleDirs); 189 } else { 190 String path = (String ) env.get("PATH"); 191 path = path + File.pathSeparator + crappleDirs; 192 env.put("PATH", path); 193 } 194 } 195 } 196 197 200 public synchronized InputStream getInputStream() { 201 if (!this.running) throw new IllegalStateException ("This LinkedJavaProcess is not yet running."); 202 return this.process.getInputStream(); 203 } 204 205 public InputStream STDOUT() { 206 return getInputStream(); 207 } 208 209 public OutputStream STDIN() { 210 return getOutputStream(); 211 } 212 213 public InputStream STDERR() { 214 return getErrorStream(); 215 } 216 217 public void mergeSTDOUT() { 218 mergeStream(STDOUT(), System.out); 219 } 220 221 public void mergeSTDERR() { 222 mergeStream(STDERR(), System.err); 223 } 224 225 private void mergeStream(InputStream in, OutputStream out) { 226 StreamCopier copier = new StreamCopier(in, out); 227 copiers.add(copier); 228 copier.start(); 229 } 230 231 234 public synchronized InputStream getErrorStream() { 235 if (!this.running) throw new IllegalStateException ("This LinkedJavaProcess is not yet running."); 236 return this.process.getErrorStream(); 237 } 238 239 242 public synchronized OutputStream getOutputStream() { 243 if (!this.running) throw new IllegalStateException ("This LinkedJavaProcess is not yet running."); 244 return this.process.getOutputStream(); 245 } 246 247 public synchronized int exitValue() { 248 if (this.process == null) throw new IllegalStateException ("This LinkedJavaProcess has not been started."); 249 int out = this.process.exitValue(); 250 this.running = false; 253 return out; 254 } 255 256 public int waitFor() throws InterruptedException { 257 Process theProcess = null; 258 259 synchronized (this) { 260 if (!this.running) throw new IllegalStateException ("This LinkedJavaProcess is not running."); 261 theProcess = this.process; 262 Assert.assertNotNull(theProcess); 263 } 264 265 int exitCode = theProcess.waitFor(); 266 267 for (Iterator i = copiers.iterator(); i.hasNext();) { 268 Thread t = (Thread ) i.next(); 269 t.join(); 270 i.remove(); 271 } 272 273 synchronized (this) { 274 this.running = false; 275 } 276 277 return exitCode; 278 279 } 280 281 } | Popular Tags |