1 7 34 35 package com.sun.tools.example.debug.tty; 36 37 import com.sun.jdi.*; 38 import com.sun.jdi.connect.*; 39 import com.sun.jdi.request.EventRequestManager; 40 import com.sun.jdi.request.ExceptionRequest; 41 import com.sun.jdi.request.ThreadStartRequest; 42 import com.sun.jdi.request.ThreadDeathRequest; 43 44 import java.util.*; 45 import java.util.regex.*; 46 import java.io.*; 47 48 class VMConnection { 49 50 private VirtualMachine vm; 51 private Process process = null; 52 private int outputCompleteCount = 0; 53 54 private final Connector connector; 55 private final Map connectorArgs; 56 private final int traceFlags; 57 58 synchronized void notifyOutputComplete() { 59 outputCompleteCount++; 60 notifyAll(); 61 } 62 63 synchronized void waitOutputComplete() { 64 if (process != null) { 66 while (outputCompleteCount < 2) { 67 try {wait();} catch (InterruptedException e) {} 68 } 69 } 70 } 71 72 private Connector findConnector(String name) { 73 List connectors = Bootstrap.virtualMachineManager().allConnectors(); 74 Iterator iter = connectors.iterator(); 75 while (iter.hasNext()) { 76 Connector connector = (Connector)iter.next(); 77 if (connector.name().equals(name)) { 78 return connector; 79 } 80 } 81 return null; 82 } 83 84 private Map parseConnectorArgs(Connector connector, String argString) { 85 Map arguments = connector.defaultArguments(); 86 87 94 String regexPattern = 95 "(quote=[^,]+,)|" + "(\\w+=)" + "(((\"[^\"]*\")|" + "('[^']*')|" + "([^,'\"]+))+,)"; Pattern p = Pattern.compile(regexPattern); 101 Matcher m = p.matcher(argString); 102 while (m.find()) { 103 int startPosition = m.start(); 104 int endPosition = m.end(); 105 if (startPosition > 0) { 106 109 throw new IllegalArgumentException 110 (MessageOutput.format("Illegal connector argument", 111 argString)); 112 } 113 114 String token = argString.substring(startPosition, endPosition); 115 int index = token.indexOf('='); 116 String name = token.substring(0, index); 117 String value = token.substring(index + 1, 118 token.length() - 1); 120 Connector.Argument argument = (Connector.Argument)arguments.get(name); 121 if (argument == null) { 122 throw new IllegalArgumentException 123 (MessageOutput.format("Argument is not defined for connector:", 124 new Object [] {name, connector.name()})); 125 } 126 argument.setValue(value); 127 128 argString = argString.substring(endPosition); m = p.matcher(argString); } 131 if ((! argString.equals(",")) && (argString.length() > 0)) { 132 136 throw new IllegalArgumentException 137 (MessageOutput.format("Illegal connector argument", argString)); 138 } 139 return arguments; 140 } 141 142 VMConnection(String connectSpec, int traceFlags) { 143 String nameString; 144 String argString; 145 int index = connectSpec.indexOf(':'); 146 if (index == -1) { 147 nameString = connectSpec; 148 argString = ""; 149 } else { 150 nameString = connectSpec.substring(0, index); 151 argString = connectSpec.substring(index + 1); 152 } 153 154 connector = findConnector(nameString); 155 if (connector == null) { 156 throw new IllegalArgumentException 157 (MessageOutput.format("No connector named:", nameString)); 158 } 159 160 connectorArgs = parseConnectorArgs(connector, argString); 161 this.traceFlags = traceFlags; 162 } 163 164 synchronized VirtualMachine open() { 165 if (connector instanceof LaunchingConnector) { 166 vm = launchTarget(); 167 } else if (connector instanceof AttachingConnector) { 168 vm = attachTarget(); 169 } else if (connector instanceof ListeningConnector) { 170 vm = listenTarget(); 171 } else { 172 throw new InternalError 173 (MessageOutput.format("Invalid connect type")); 174 } 175 vm.setDebugTraceMode(traceFlags); 176 if (vm.canBeModified()){ 177 setEventRequests(vm); 178 resolveEventRequests(); 179 } 180 186 if (Env.getSourcePath().length() == 0) { 187 if (vm instanceof PathSearchingVirtualMachine) { 188 PathSearchingVirtualMachine psvm = 189 (PathSearchingVirtualMachine) vm; 190 Env.setSourcePath(psvm.classPath()); 191 } else { 192 Env.setSourcePath("."); 193 } 194 } 195 196 return vm; 197 } 198 199 boolean setConnectorArg(String name, String value) { 200 203 if (vm != null) { 204 return false; 205 } 206 207 Connector.Argument argument = (Connector.Argument)connectorArgs.get(name); 208 if (argument == null) { 209 return false; 210 } 211 argument.setValue(value); 212 return true; 213 } 214 215 String connectorArg(String name) { 216 Connector.Argument argument = (Connector.Argument)connectorArgs.get(name); 217 if (argument == null) { 218 return ""; 219 } 220 return argument.value(); 221 } 222 223 public synchronized VirtualMachine vm() { 224 if (vm == null) { 225 throw new VMNotConnectedException(); 226 } else { 227 return vm; 228 } 229 } 230 231 boolean isOpen() { 232 return (vm != null); 233 } 234 235 boolean isLaunch() { 236 return (connector instanceof LaunchingConnector); 237 } 238 239 public void disposeVM() { 240 try { 241 if (vm != null) { 242 vm.dispose(); 243 vm = null; 244 } 245 } finally { 246 if (process != null) { 247 process.destroy(); 248 process = null; 249 } 250 waitOutputComplete(); 251 } 252 } 253 254 private void setEventRequests(VirtualMachine vm) { 255 EventRequestManager erm = vm.eventRequestManager(); 256 257 Commands evaluator = new Commands(); 266 evaluator.commandCatchException 267 (new StringTokenizer("uncaught java.lang.Throwable")); 268 269 ThreadStartRequest tsr = erm.createThreadStartRequest(); 270 tsr.enable(); 271 ThreadDeathRequest tdr = erm.createThreadDeathRequest(); 272 tdr.enable(); 273 } 274 275 private void resolveEventRequests() { 276 Env.specList.resolveAll(); 277 } 278 279 private void dumpStream(InputStream stream) throws IOException { 280 BufferedReader in = 281 new BufferedReader(new InputStreamReader(stream)); 282 int i; 283 try { 284 while ((i = in.read()) != -1) { 285 MessageOutput.printDirect((char)i); } 288 } catch (IOException ex) { 289 String s = ex.getMessage(); 290 if (!s.startsWith("Bad file number")) { 291 throw ex; 292 } 293 } 297 } 298 299 304 private void displayRemoteOutput(final InputStream stream) { 305 Thread thr = new Thread ("output reader") { 306 public void run() { 307 try { 308 dumpStream(stream); 309 } catch (IOException ex) { 310 MessageOutput.fatalError("Failed reading output"); 311 } finally { 312 notifyOutputComplete(); 313 } 314 } 315 }; 316 thr.setPriority(Thread.MAX_PRIORITY-1); 317 thr.start(); 318 } 319 320 private void dumpFailedLaunchInfo(Process process) { 321 try { 322 dumpStream(process.getErrorStream()); 323 dumpStream(process.getInputStream()); 324 } catch (IOException e) { 325 MessageOutput.println("Unable to display process output:", 326 e.getMessage()); 327 } 328 } 329 330 331 private VirtualMachine launchTarget() { 332 LaunchingConnector launcher = (LaunchingConnector)connector; 333 try { 334 VirtualMachine vm = launcher.launch(connectorArgs); 335 process = vm.process(); 336 displayRemoteOutput(process.getErrorStream()); 337 displayRemoteOutput(process.getInputStream()); 338 return vm; 339 } catch (IOException ioe) { 340 ioe.printStackTrace(); 341 MessageOutput.fatalError("Unable to launch target VM."); 342 } catch (IllegalConnectorArgumentsException icae) { 343 icae.printStackTrace(); 344 MessageOutput.fatalError("Internal debugger error."); 345 } catch (VMStartException vmse) { 346 MessageOutput.println("vmstartexception", vmse.getMessage()); 347 MessageOutput.println(); 348 dumpFailedLaunchInfo(vmse.process()); 349 MessageOutput.fatalError("Target VM failed to initialize."); 350 } 351 return null; } 353 354 355 private VirtualMachine attachTarget() { 356 AttachingConnector attacher = (AttachingConnector)connector; 357 try { 358 return attacher.attach(connectorArgs); 359 } catch (IOException ioe) { 360 ioe.printStackTrace(); 361 MessageOutput.fatalError("Unable to attach to target VM."); 362 } catch (IllegalConnectorArgumentsException icae) { 363 icae.printStackTrace(); 364 MessageOutput.fatalError("Internal debugger error."); 365 } 366 return null; } 368 369 370 private VirtualMachine listenTarget() { 371 ListeningConnector listener = (ListeningConnector)connector; 372 try { 373 String retAddress = listener.startListening(connectorArgs); 374 MessageOutput.println("Listening at address:", retAddress); 375 vm = listener.accept(connectorArgs); 376 listener.stopListening(connectorArgs); 377 return vm; 378 } catch (IOException ioe) { 379 ioe.printStackTrace(); 380 MessageOutput.fatalError("Unable to attach to target VM."); 381 } catch (IllegalConnectorArgumentsException icae) { 382 icae.printStackTrace(); 383 MessageOutput.fatalError("Internal debugger error."); 384 } 385 return null; } 387 } 388 | Popular Tags |