/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.debug.tests.core; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.ILineBreakpoint; import org.eclipse.debug.core.model.IProcess; import org.eclipse.jdt.debug.core.IJavaThread; import org.eclipse.jdt.debug.testplugin.DebugElementKindEventDetailWaiter; import org.eclipse.jdt.debug.testplugin.DebugEventWaiter; import org.eclipse.jdt.debug.tests.AbstractDebugTest; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.jdt.launching.IVMConnector; import org.eclipse.jdt.launching.JavaRuntime; import com.sun.jdi.connect.Connector; /** * Tests attaching to a remote java application */ public class RemoteJavaApplicationTests extends AbstractDebugTest { public RemoteJavaApplicationTests(String name) { super(name); } /** * Tests a Standard (Socket Attach) VM connection. * @throws Exception */ public void testAttach() throws Exception { String typeName = "Breakpoints"; createLineBreakpoint(52, typeName); // create launch config to launch VM in debug mode waiting for attach ILaunchConfigurationType type = getLaunchManager().getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION); ILaunchConfigurationWorkingCopy config = type.newInstance(null, "Launch Remote VM"); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, "Breakpoints"); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, get14Project().getElementName()); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, "-Djava.compiler=NONE -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8000,suspend=y,server=y"); // use 'java' instead of 'javaw' to launch tests (javaw is problematic on JDK1.4.2) Map<String, String> map = new HashMap<String, String>(1); map.put(IJavaLaunchConfigurationConstants.ATTR_JAVA_COMMAND, "java"); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE_SPECIFIC_ATTRS_MAP, map); ILaunchConfiguration launchRemoteVMConfig = config.doSave(); // create a launch config to do the attach type = getLaunchManager().getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_REMOTE_JAVA_APPLICATION); config = type.newInstance(null, "Remote Breakpoints"); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, get14Project().getElementName()); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_ALLOW_TERMINATE, true); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_CONNECTOR, IJavaLaunchConfigurationConstants.ID_SOCKET_ATTACH_VM_CONNECTOR); IVMConnector connector = JavaRuntime.getVMConnector(IJavaLaunchConfigurationConstants.ID_SOCKET_ATTACH_VM_CONNECTOR); Map<String, ? extends Connector.Argument> def = connector.getDefaultArguments(); Map<String, String> argMap = new HashMap<String, String>(def.size()); Iterator<String> iter = connector.getArgumentOrder().iterator(); while (iter.hasNext()) { String key = iter.next(); Connector.Argument arg = def.get(key); argMap.put(key, arg.toString()); } config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CONNECT_MAP, argMap); ILaunchConfiguration attachConfig = config.doSave(); // launch remote VM ILaunch launch = launchRemoteVMConfig.launch(ILaunchManager.RUN_MODE, null); // attach IJavaThread thread= null; try { CoreException exception = null; int attempts = 0; boolean connected = false; while ((attempts < 2) && !connected) { try { attempts++; exception = null; thread= launchToBreakpoint(attachConfig); connected = true; } catch (CoreException e) { // try again, in case the VM is not yet ready exception = e; Thread.sleep(2000); } } if (exception != null) { throw exception; } assertNotNull("Breakpoint not hit within timeout period", thread); IBreakpoint hit = getBreakpoint(thread); assertNotNull("suspended, but not by breakpoint", hit); assertTrue("suspended, but not by line breakpoint", hit instanceof ILineBreakpoint); ILineBreakpoint breakpoint= (ILineBreakpoint) hit; int lineNumber = breakpoint.getLineNumber(); int stackLine = thread.getTopStackFrame().getLineNumber(); assertTrue("line numbers of breakpoint and stack frame do not match", lineNumber == stackLine); breakpoint.delete(); } finally { terminateAndRemove(thread); removeAllBreakpoints(); DebugPlugin.getDefault().getLaunchManager().removeLaunch(launch); } } /** * Tests a Standard (Socket Listen) VM connection. * @throws Exception */ public void testListen() throws Exception { String typeName = "Breakpoints"; createLineBreakpoint(52, typeName); // create a launch config to listen for the vm ILaunchConfigurationType type = getLaunchManager().getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_REMOTE_JAVA_APPLICATION); ILaunchConfigurationWorkingCopy config = type.newInstance(null, "Remote Breakpoints"); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, get14Project().getElementName()); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_ALLOW_TERMINATE, true); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_CONNECTOR, IJavaLaunchConfigurationConstants.ID_SOCKET_LISTEN_VM_CONNECTOR); IVMConnector connector = JavaRuntime.getVMConnector(IJavaLaunchConfigurationConstants.ID_SOCKET_LISTEN_VM_CONNECTOR); Map<String, ? extends Connector.Argument> def = connector.getDefaultArguments(); Map<String, String> argMap = new HashMap<String, String>(def.size()); Iterator<String> iter = connector.getArgumentOrder().iterator(); while (iter.hasNext()) { String key = iter.next(); Connector.Argument arg = def.get(key); argMap.put(key, arg.toString()); } config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CONNECT_MAP, argMap); ILaunchConfiguration listenConfig = config.doSave(); // create launch config to launch VM that will connect to the waiting listener type = getLaunchManager().getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION); config = type.newInstance(null, "Launch Remote VM"); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, "Breakpoints"); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, get14Project().getElementName()); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, "-Djava.compiler=NONE -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8000,suspend=y,server=n"); // use 'java' instead of 'javaw' to launch tests (javaw is problematic on JDK1.4.2) Map<String, String> map = new HashMap<String, String>(1); map.put(IJavaLaunchConfigurationConstants.ATTR_JAVA_COMMAND, "java"); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE_SPECIFIC_ATTRS_MAP, map); ILaunchConfiguration launchRemoteVMConfig = config.doSave(); ILaunch listenerLaunch = null; IJavaThread thread = null; try { DebugEventWaiter waiter= new DebugElementKindEventDetailWaiter(DebugEvent.MODEL_SPECIFIC, IProcess.class, IJavaLaunchConfigurationConstants.DETAIL_CONFIG_READY_TO_ACCEPT_REMOTE_VM_CONNECTION); waiter.setTimeout(DEFAULT_TIMEOUT); IProcess process = null; CoreException exception = null; int attempts = 0; boolean connected = false; while ((attempts < 2) && !connected) { try { attempts++; exception = null; process = (IProcess)launchAndWait(listenConfig,waiter); connected = true; } catch (CoreException e) { // try again, in case the VM is not yet ready exception = e; Thread.sleep(2000); } } if (exception != null) { throw exception; } assertNotNull("Launch of the not successful", process); listenerLaunch = process.getLaunch(); waiter= new DebugElementKindEventDetailWaiter(DebugEvent.SUSPEND, IJavaThread.class, DebugEvent.BREAKPOINT); waiter.setTimeout(DEFAULT_TIMEOUT); exception = null; attempts = 0; connected = false; while ((attempts < 2) && !connected) { try { attempts++; exception = null; thread = (IJavaThread)launchAndWait(launchRemoteVMConfig,ILaunchManager.RUN_MODE,waiter,true); connected = true; } catch (CoreException e) { // try again, in case the VM is not yet ready exception = e; Thread.sleep(2000); } } if (exception != null) { throw exception; } assertNotNull("Breakpoint not hit within timeout period", thread); IBreakpoint hit = getBreakpoint(thread); assertNotNull("suspended, but not by breakpoint", hit); assertTrue("suspended, but not by line breakpoint", hit instanceof ILineBreakpoint); ILineBreakpoint breakpoint= (ILineBreakpoint) hit; int lineNumber = breakpoint.getLineNumber(); int stackLine = thread.getTopStackFrame().getLineNumber(); assertTrue("line numbers of breakpoint and stack frame do not match", lineNumber == stackLine); breakpoint.delete(); } finally { terminateAndRemove(thread); removeAllBreakpoints(); if (listenerLaunch != null){ DebugPlugin.getDefault().getLaunchManager().removeLaunch(listenerLaunch); } } } }