1 8 package org.codehaus.aspectwerkz.hook; 9 10 import com.sun.jdi.VirtualMachine; 11 12 import java.io.File ; 13 import java.io.IOException ; 14 import java.util.StringTokenizer ; 15 16 87 public class ProcessStarter { 88 91 final static String CL_PRE_PROCESSOR_CLASSNAME_PROPERTY = "aspectwerkz.classloader.clpreprocessor"; 92 93 96 private final static String CL_BOOTCLASSPATH_FORCE_DEFAULT = "." + File.separatorChar + "_boot"; 97 98 101 private final static String CL_BOOTCLASSPATH_FORCE_PROPERTY = "aspectwerkz.classloader.clbootclasspath"; 102 103 106 private final static String CONNECTION_WAIT_PROPERTY = "aspectwerkz.classloader.wait"; 107 108 111 private Process process = null; 112 113 116 private boolean executeShutdownHook = true; 117 118 121 private Thread inThread; 122 123 126 private Thread outThread; 127 128 131 private Thread errThread; 132 133 136 private static boolean hasCanRedefineClass() { 137 try { 138 VirtualMachine.class.getMethod("canRedefineClasses", new Class []{}); 139 } catch (NoSuchMethodException e) { 140 return false; 141 } 142 return true; 143 } 144 145 private int run(String [] args) { 146 String [] javaArgs = parseJavaCommandLine(args); 148 String optionArgs = javaArgs[0]; 149 String cpArgs = javaArgs[1]; 150 String mainArgs = javaArgs[2]; 151 String options = optionArgs + " -cp " + cpArgs; 152 String clp = System.getProperty( 153 CL_PRE_PROCESSOR_CLASSNAME_PROPERTY, 154 "org.codehaus.aspectwerkz.hook.impl.ClassLoaderPreProcessorImpl" 155 ); 156 157 if (!hasCanRedefineClass() || (System.getProperty(CL_BOOTCLASSPATH_FORCE_PROPERTY) != null)) { 160 String bootDir = System.getProperty(CL_BOOTCLASSPATH_FORCE_PROPERTY, CL_BOOTCLASSPATH_FORCE_DEFAULT); 161 if (System.getProperty(CL_BOOTCLASSPATH_FORCE_PROPERTY) != null) { 162 System.out.println("HotSwap deactivated, using bootclasspath: " + bootDir); 163 } else { 164 System.out.println("HotSwap not supported by this java version, using bootclasspath: " + bootDir); 165 } 166 ClassLoaderPatcher.patchClassLoader(clp, bootDir); 167 BootClasspathStarter starter = new BootClasspathStarter(options, mainArgs, bootDir); 168 try { 169 process = starter.launchVM(); 170 } catch (IOException e) { 171 System.err.println("failed to launch process :" + starter.getCommandLine()); 172 e.printStackTrace(); 173 return -1; 174 } 175 176 redirectStdoutStreams(); 179 } else { 180 JDWPStarter starter = new JDWPStarter(options, mainArgs, "dt_socket", "9300"); 182 try { 183 process = starter.launchVM(); 184 } catch (IOException e) { 185 System.err.println("failed to launch process :" + starter.getCommandLine()); 186 e.printStackTrace(); 187 return -1; 188 } 189 190 redirectStdoutStreams(); 193 194 int secondsToWait = 0; 196 try { 197 secondsToWait = Integer.parseInt(System.getProperty(CONNECTION_WAIT_PROPERTY, "0")); 198 } catch (NumberFormatException nfe) { 199 ; 200 } 201 VirtualMachine vm = ClassLoaderPatcher.hotswapClassLoader( 202 clp, 203 starter.getTransport(), 204 starter.getAddress(), 205 secondsToWait 206 ); 207 if (vm == null) { 208 process.destroy(); 209 } else { 210 vm.resume(); 211 vm.dispose(); 212 } 213 } 214 215 redirectOtherStreams(); 217 218 Thread shutdownHook = new Thread () { 220 public void run() { 221 shutdown(); 222 } 223 }; 224 try { 225 Runtime.getRuntime().addShutdownHook(shutdownHook); 226 int exitCode = process.waitFor(); 227 executeShutdownHook = false; 228 return exitCode; 229 } catch (Exception e) { 230 executeShutdownHook = false; 231 e.printStackTrace(); 232 return -1; 233 } 234 } 235 236 239 private void shutdown() { 240 if (executeShutdownHook) { 241 process.destroy(); 242 } 243 try { 244 outThread.join(); 245 errThread.join(); 246 } catch (InterruptedException e) { 247 ; 248 } 249 } 250 251 254 private void redirectStdoutStreams() { 255 outThread = new StreamRedirectThread("out.redirect", process.getInputStream(), System.out); 256 outThread.start(); 257 } 258 259 262 private void redirectOtherStreams() { 263 inThread = new StreamRedirectThread("in.redirect", System.in, process.getOutputStream()); 264 inThread.setDaemon(true); 265 errThread = new StreamRedirectThread("err.redirect", process.getErrorStream(), System.err); 266 inThread.start(); 267 errThread.start(); 268 } 269 270 public static void main(String [] args) { 271 System.exit((new ProcessStarter()).run(args)); 272 } 273 274 private static String escapeWhiteSpace(String s) { 275 if (s.indexOf(' ') > 0) { 276 StringBuffer sb = new StringBuffer (); 277 StringTokenizer st = new StringTokenizer (s, " ", true); 278 String current = null; 279 while (st.hasMoreTokens()) { 280 current = st.nextToken(); 281 if (" ".equals(current)) { 282 sb.append("\\ "); 283 } else { 284 sb.append(current); 285 } 286 } 287 return sb.toString(); 288 } else { 289 return s; 290 } 291 } 292 293 299 public static String removeEmbracingQuotes(String s) { 300 if ((s.length() >= 2) && (s.charAt(0) == '"') && (s.charAt(s.length() - 1) == '"')) { 301 return s.substring(1, s.length() - 1); 302 } else if ((s.length() >= 2) && (s.charAt(0) == '\'') && (s.charAt(s.length() - 1) == '\'')) { 303 return s.substring(1, s.length() - 1); 304 } else { 305 return s; 306 } 307 } 308 309 315 public String [] parseJavaCommandLine(String [] args) { 316 StringBuffer optionsArgB = new StringBuffer (); 317 StringBuffer cpOptionsArgB = new StringBuffer (); 318 StringBuffer mainArgB = new StringBuffer (); 319 String previous = null; 320 boolean foundMain = false; 321 for (int i = 0; i < args.length; i++) { 322 if (args[i].startsWith("-") && !foundMain) { 324 if (!("-cp".equals(args[i])) && !("-classpath").equals(args[i])) { 325 optionsArgB.append(args[i]).append(" "); 326 } 327 } else if (!foundMain && ("-cp".equals(previous) || "-classpath".equals(previous))) { 328 if (cpOptionsArgB.length() > 0) { 329 cpOptionsArgB.append( 330 (System.getProperty("os.name", "").toLowerCase().indexOf("windows") >= 0) 331 ? ";" 332 : ":" 333 ); 334 } 335 cpOptionsArgB.append(removeEmbracingQuotes(args[i])); 336 } else { 337 foundMain = true; 338 mainArgB.append(args[i]).append(" "); 339 } 340 previous = args[i]; 341 } 342 343 StringBuffer classPath = new StringBuffer (); 345 if (System.getProperty("os.name", "").toLowerCase().indexOf("windows") >= 0) { 346 classPath = classPath.append("\"").append(cpOptionsArgB.toString()).append("\""); 347 } else { 348 classPath = classPath.append(escapeWhiteSpace(cpOptionsArgB.toString())); 349 } 350 String [] res = new String []{ 351 optionsArgB.toString(), classPath.toString(), mainArgB.toString() 352 }; 353 return res; 354 } 355 } | Popular Tags |