1 11 package org.eclipse.jdt.internal.launching; 12 13 14 import java.io.File ; 15 import java.io.IOException ; 16 import java.io.InterruptedIOException ; 17 import java.util.ArrayList ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 22 import org.eclipse.core.runtime.CoreException; 23 import org.eclipse.core.runtime.IPath; 24 import org.eclipse.core.runtime.IProgressMonitor; 25 import org.eclipse.core.runtime.IStatus; 26 import org.eclipse.core.runtime.NullProgressMonitor; 27 import org.eclipse.core.runtime.Path; 28 import org.eclipse.core.runtime.Platform; 29 import org.eclipse.core.runtime.Status; 30 import org.eclipse.core.runtime.SubProgressMonitor; 31 import org.eclipse.debug.core.DebugPlugin; 32 import org.eclipse.debug.core.ILaunch; 33 import org.eclipse.debug.core.IStatusHandler; 34 import org.eclipse.debug.core.model.IDebugTarget; 35 import org.eclipse.debug.core.model.IProcess; 36 import org.eclipse.debug.core.model.IStreamsProxy; 37 import org.eclipse.jdi.Bootstrap; 38 import org.eclipse.jdt.debug.core.JDIDebugModel; 39 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; 40 import org.eclipse.jdt.launching.IVMInstall; 41 import org.eclipse.jdt.launching.JavaRuntime; 42 import org.eclipse.jdt.launching.SocketUtil; 43 import org.eclipse.jdt.launching.VMRunnerConfiguration; 44 45 import com.sun.jdi.VirtualMachine; 46 import com.sun.jdi.connect.Connector; 47 import com.sun.jdi.connect.IllegalConnectorArgumentsException; 48 import com.sun.jdi.connect.ListeningConnector; 49 50 54 public class StandardVMDebugger extends StandardVMRunner { 55 56 57 60 protected static final String JAVA_JVM_VERSION = "JAVA_JVM_VERSION"; 62 69 protected static final String JRE = "jre"; 71 78 protected static final String BIN = "bin"; 80 85 class ConnectRunnable implements Runnable { 86 87 private VirtualMachine fVirtualMachine = null; 88 private ListeningConnector fConnector = null; 89 private Map fConnectionMap = null; 90 private Exception fException = null; 91 92 99 public ConnectRunnable(ListeningConnector connector, Map map) { 100 fConnector = connector; 101 fConnectionMap = map; 102 } 103 104 public void run() { 105 try { 106 fVirtualMachine = fConnector.accept(fConnectionMap); 107 } catch (IOException e) { 108 fException = e; 109 } catch (IllegalConnectorArgumentsException e) { 110 fException = e; 111 } 112 } 113 114 119 public VirtualMachine getVirtualMachine() { 120 return fVirtualMachine; 121 } 122 123 128 public Exception getException() { 129 return fException; 130 } 131 } 132 133 136 public StandardVMDebugger(IVMInstall vmInstance) { 137 super(vmInstance); 138 } 139 140 143 public void run(VMRunnerConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException { 144 145 if (monitor == null) { 146 monitor = new NullProgressMonitor(); 147 } 148 149 IProgressMonitor subMonitor = new SubProgressMonitor(monitor, 1); 150 subMonitor.beginTask(LaunchingMessages.StandardVMDebugger_Launching_VM____1, 4); 151 subMonitor.subTask(LaunchingMessages.StandardVMDebugger_Finding_free_socket____2); 152 153 int port= SocketUtil.findFreePort(); 154 if (port == -1) { 155 abort(LaunchingMessages.StandardVMDebugger_Could_not_find_a_free_socket_for_the_debugger_1, null, IJavaLaunchConfigurationConstants.ERR_NO_SOCKET_AVAILABLE); 156 } 157 158 subMonitor.worked(1); 159 160 if (monitor.isCanceled()) { 162 return; 163 } 164 165 subMonitor.subTask(LaunchingMessages.StandardVMDebugger_Constructing_command_line____3); 166 167 String program= constructProgramString(config); 168 169 List arguments= new ArrayList (12); 170 171 arguments.add(program); 172 173 String [] allVMArgs = combineVmArgs(config, fVMInstance); 176 addArguments(allVMArgs, arguments); 177 addBootClassPathArguments(arguments, config); 178 179 String [] cp= config.getClassPath(); 180 if (cp.length > 0) { 181 arguments.add("-classpath"); arguments.add(convertClassPath(cp)); 183 } 184 double version = getJavaVersion(); 185 if (version < 1.5) { 186 arguments.add("-Xdebug"); arguments.add("-Xnoagent"); } 189 190 if (version < 1.4) { 192 arguments.add("-Djava.compiler=NONE"); } 194 if (version < 1.5) { 195 arguments.add("-Xrunjdwp:transport=dt_socket,suspend=y,address=localhost:" + port); } else { 197 arguments.add("-agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:" + port); } 199 200 arguments.add(config.getClassToLaunch()); 201 addArguments(config.getProgramArguments(), arguments); 202 String [] cmdLine= new String [arguments.size()]; 203 arguments.toArray(cmdLine); 204 205 String [] envp = prependJREPath(config.getEnvironment(), new Path(program)); 209 210 if (monitor.isCanceled()) { 212 return; 213 } 214 215 subMonitor.worked(1); 216 subMonitor.subTask(LaunchingMessages.StandardVMDebugger_Starting_virtual_machine____4); 217 218 ListeningConnector connector= getConnector(); 219 if (connector == null) { 220 abort(LaunchingMessages.StandardVMDebugger_Couldn__t_find_an_appropriate_debug_connector_2, null, IJavaLaunchConfigurationConstants.ERR_CONNECTOR_NOT_AVAILABLE); 221 } 222 Map map= connector.defaultArguments(); 223 224 specifyArguments(map, port); 225 Process p= null; 226 try { 227 try { 228 if (monitor.isCanceled()) { 230 return; 231 } 232 233 connector.startListening(map); 234 235 File workingDir = getWorkingDir(config); 236 p = exec(cmdLine, workingDir, envp); 237 if (p == null) { 238 return; 239 } 240 241 if (monitor.isCanceled()) { 243 p.destroy(); 244 return; 245 } 246 247 IProcess process= newProcess(launch, p, renderProcessLabel(cmdLine), getDefaultProcessMap()); 248 process.setAttribute(IProcess.ATTR_CMDLINE, renderCommandLine(cmdLine)); 249 subMonitor.worked(1); 250 subMonitor.subTask(LaunchingMessages.StandardVMDebugger_Establishing_debug_connection____5); 251 boolean retry= false; 252 do { 253 try { 254 255 ConnectRunnable runnable = new ConnectRunnable(connector, map); 256 Thread connectThread = new Thread (runnable, "Listening Connector"); connectThread.setDaemon(true); 258 connectThread.start(); 259 while (connectThread.isAlive()) { 260 if (monitor.isCanceled()) { 261 try { 262 connector.stopListening(map); 263 } catch (IOException ioe) { 264 } 266 p.destroy(); 267 return; 268 } 269 try { 270 p.exitValue(); 271 try { 273 connector.stopListening(map); 274 } catch (IOException e) { 275 } 277 checkErrorMessage(process); 278 } catch (IllegalThreadStateException e) { 279 } 281 try { 282 Thread.sleep(100); 283 } catch (InterruptedException e) { 284 } 285 } 286 287 Exception ex = runnable.getException(); 288 if (ex instanceof IllegalConnectorArgumentsException) { 289 throw (IllegalConnectorArgumentsException)ex; 290 } 291 if (ex instanceof InterruptedIOException ) { 292 throw (InterruptedIOException )ex; 293 } 294 if (ex instanceof IOException ) { 295 throw (IOException )ex; 296 } 297 298 VirtualMachine vm= runnable.getVirtualMachine(); 299 if (vm != null) { 300 createDebugTarget(config, launch, port, process, vm); 301 subMonitor.worked(1); 302 subMonitor.done(); 303 } 304 return; 305 } catch (InterruptedIOException e) { 306 checkErrorMessage(process); 307 308 IStatus status = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), IJavaLaunchConfigurationConstants.ERR_VM_CONNECT_TIMEOUT, "", e); IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status); 311 312 retry= false; 313 if (handler == null) { 314 throw new CoreException(status); 316 } 317 Object result = handler.handleStatus(status, this); 318 if (result instanceof Boolean ) { 319 retry = ((Boolean )result).booleanValue(); 320 } 321 } 322 } while (retry); 323 } finally { 324 connector.stopListening(map); 325 } 326 } catch (IOException e) { 327 abort(LaunchingMessages.StandardVMDebugger_Couldn__t_connect_to_VM_4, e, IJavaLaunchConfigurationConstants.ERR_CONNECTION_FAILED); 328 } catch (IllegalConnectorArgumentsException e) { 329 abort(LaunchingMessages.StandardVMDebugger_Couldn__t_connect_to_VM_5, e, IJavaLaunchConfigurationConstants.ERR_CONNECTION_FAILED); 330 } 331 if (p != null) { 332 p.destroy(); 333 } 334 } 335 336 357 protected String [] prependJREPath(String [] env, IPath jdkpath) { 358 if(Platform.OS_WIN32.equals(Platform.getOS())) { 359 IPath jrepath = jdkpath.removeLastSegments(1); 360 if(jrepath.lastSegment().equals(BIN)) { 361 if(!jrepath.segment(jrepath.segmentCount()-2).equals(JRE)) { 362 jrepath = jrepath.removeLastSegments(1).append(JRE).append(BIN); 363 } 364 } 365 else { 366 jrepath = jrepath.append(JRE).append(BIN); 367 } 368 if(jrepath.toFile().exists()) { 369 String jrestr = jrepath.toOSString(); 370 if(env == null){ 371 Map map = DebugPlugin.getDefault().getLaunchManager().getNativeEnvironment(); 372 env = new String [map.size()]; 373 String var = null; 374 int index = 0; 375 for(Iterator iter = map.keySet().iterator(); iter.hasNext();) { 376 var = (String ) iter.next(); 377 String value = (String ) map.get(var); 378 if (value == null) { 379 value = ""; } 381 if (var.equalsIgnoreCase("path")) { if(value.indexOf(jrestr) == -1) { 383 value = jrestr+';'+value; 384 } 385 } 386 env[index] = var+"="+value; index++; 388 } 389 } else { 390 String var = null; 391 int esign = -1; 392 for(int i = 0; i < env.length; i++) { 393 esign = env[i].indexOf('='); 394 if(esign > -1) { 395 var = env[i].substring(0, esign); 396 if(var != null && var.equalsIgnoreCase("path")) { if(env[i].indexOf(jrestr) == -1) { 398 env[i] = var + "="+jrestr+';'+(esign == env.length ? "" : env[i].substring(esign+1)); break; 400 } 401 } 402 } 403 } 404 } 405 } 406 } 407 return super.prependJREPath(env, jdkpath); 408 } 409 410 420 protected IDebugTarget createDebugTarget(VMRunnerConfiguration config, ILaunch launch, int port, IProcess process, VirtualMachine vm) { 421 return JDIDebugModel.newDebugTarget(launch, vm, renderDebugTarget(config.getClassToLaunch(), port), process, true, false, config.isResumeOnStartup()); 422 } 423 424 428 private double getJavaVersion() { 429 LibraryInfo libInfo = LaunchingPlugin.getLibraryInfo(fVMInstance.getInstallLocation().getAbsolutePath()); 430 if (libInfo == null) { 431 return 0D; 432 } 433 String version = libInfo.getVersion(); 434 int index = version.indexOf("."); int nextIndex = version.indexOf(".", index+1); try { 437 if (index > 0 && nextIndex>index) { 438 return Double.parseDouble(version.substring(0,nextIndex)); 439 } 440 return Double.parseDouble(version); 441 } catch (NumberFormatException e) { 442 return 0D; 443 } 444 445 } 446 447 452 protected void checkErrorMessage(IProcess process) throws CoreException { 453 IStreamsProxy streamsProxy = process.getStreamsProxy(); 454 if (streamsProxy != null) { 455 String errorMessage= streamsProxy.getErrorStreamMonitor().getContents(); 456 if (errorMessage.length() == 0) { 457 errorMessage= streamsProxy.getOutputStreamMonitor().getContents(); 458 } 459 if (errorMessage.length() != 0) { 460 abort(errorMessage, null, IJavaLaunchConfigurationConstants.ERR_VM_LAUNCH_ERROR); 461 } 462 } 463 } 464 465 470 protected void specifyArguments(Map map, int portNumber) { 471 Connector.IntegerArgument port= (Connector.IntegerArgument) map.get("port"); port.setValue(portNumber); 474 475 Connector.IntegerArgument timeoutArg= (Connector.IntegerArgument) map.get("timeout"); if (timeoutArg != null) { 477 int timeout = JavaRuntime.getPreferences().getInt(JavaRuntime.PREF_CONNECT_TIMEOUT); 478 timeoutArg.setValue(timeout); 479 } 480 } 481 482 486 protected ListeningConnector getConnector() { 487 List connectors= Bootstrap.virtualMachineManager().listeningConnectors(); 488 for (int i= 0; i < connectors.size(); i++) { 489 ListeningConnector c= (ListeningConnector) connectors.get(i); 490 if ("com.sun.jdi.SocketListen".equals(c.name())) return c; 492 } 493 return null; 494 } 495 496 } 497 | Popular Tags |