java local debugger attach - initial

This commit is contained in:
Egor.Ushakov
2016-07-18 17:15:23 +03:00
parent 1ab068715c
commit 76f00d7a91
3 changed files with 169 additions and 13 deletions
@@ -0,0 +1,142 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.debugger.engine;
import com.intellij.debugger.DebugEnvironment;
import com.intellij.debugger.DebuggerManagerEx;
import com.intellij.debugger.DefaultDebugEnvironment;
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.RunManager;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.ConfigurationTypeUtil;
import com.intellij.execution.configurations.RemoteConnection;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.process.ProcessInfo;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.internal.DebugAttachDetector;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugProcessStarter;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.attach.XDefaultLocalAttachGroup;
import com.intellij.xdebugger.attach.XLocalAttachDebugger;
import com.intellij.xdebugger.attach.XLocalAttachDebuggerProvider;
import com.intellij.xdebugger.attach.XLocalAttachGroup;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
/**
* @author egor
*/
public class JavaAttachDebuggerProvider implements XLocalAttachDebuggerProvider {
private static final XLocalAttachDebugger ourAttachDebugger = new XLocalAttachDebugger() {
@NotNull
@Override
public String getDebuggerDisplayName() {
return "Java Debugger";
}
@Override
public XDebugSession attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException {
Pair<String, Integer> address = getAttachAddress(processInfo);
assert address != null;
// TODO: first need to remove circular dependency with execution-impl
//RunnerAndConfigurationSettings runSettings = RunManager.getInstance(project)
// .createRunConfiguration(StringUtil.notNullize(address.first) + ":" + address.second,
// RemoteConfigurationType.getInstance().getFactory());
//
//RemoteConfiguration configuration = (RemoteConfiguration)runSettings.getConfiguration();
//configuration.HOST = address.first;
//configuration.PORT = String.valueOf(address.second);
//configuration.USE_SOCKET_TRANSPORT = true;
//configuration.SERVER_MODE = false;
//
//ProgramRunnerUtil.executeConfiguration(project, runSettings, DefaultDebugExecutor.getDebugExecutorInstance());
String name = StringUtil.notNullize(address.first) + ":" + address.second;
RunnerAndConfigurationSettings runSettings = RunManager.getInstance(project)
.createRunConfiguration(name, ConfigurationTypeUtil.findConfigurationType("Remote").getConfigurationFactories()[0]);
RemoteConnection remoteConnection = new RemoteConnection(true, address.first, String.valueOf(address.second), false);
ExecutionEnvironment env = new ExecutionEnvironmentBuilder(project, DefaultDebugExecutor.getDebugExecutorInstance())
.runProfile(runSettings.getConfiguration())
.build();
DebugEnvironment environment = new DefaultDebugEnvironment(env, new RemoteStateState(project, remoteConnection), remoteConnection, 0);
final DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(env.getProject()).attachVirtualMachine(environment);
if (debuggerSession == null) {
return null;
}
return XDebuggerManager.getInstance(project).startSessionAndShowTab(name, null, new XDebugProcessStarter() {
@Override
@NotNull
public XDebugProcess start(@NotNull XDebugSession session) {
return JavaDebugProcess.create(session, debuggerSession);
}
});
}
};
private static final XLocalAttachGroup ourAttachGroup = new XDefaultLocalAttachGroup() {
@Override
public int getOrder() {
return 1;
}
@NotNull
@Override
public String getGroupName() {
return "Java";
}
@NotNull
@Override
public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info) {
return info.getCommandLine();
}
};
@NotNull
@Override
public XLocalAttachGroup getAttachGroup() {
return ourAttachGroup;
}
@NotNull
@Override
public List<XLocalAttachDebugger> getAvailableDebuggers(@NotNull Project project,
@NotNull ProcessInfo processInfo,
@NotNull UserDataHolder contextHolder) {
Pair<String, Integer> address = getAttachAddress(processInfo);
if (address != null) {
return Collections.singletonList(ourAttachDebugger);
}
return Collections.emptyList();
}
private static Pair<String, Integer> getAttachAddress(ProcessInfo processInfo) {
return DebugAttachDetector.getAttachAddress(StringUtil.split(processInfo.getCommandLine(), " "));
}
}
@@ -22,9 +22,11 @@ import com.intellij.notification.Notifications;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.util.net.NetUtils;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -40,14 +42,10 @@ public class DebugAttachDetector {
private boolean myAttached;
private boolean myReady;
public DebugAttachDetector() {
ApplicationEx app = ApplicationManagerEx.getApplicationEx();
if (!app.isInternal()
|| app.isUnitTestMode()
|| app.isHeadlessEnvironment()
|| "true".equals(System.getProperty("idea.debug.mode"))) return;
for (String argument : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
public static Pair<String, Integer> getAttachAddress(List<String> arguments) {
String host = null;
int port = -1;
for (String argument : arguments) {
if (argument.startsWith("-agentlib:jdwp") && argument.contains("transport=dt_socket")) {
String[] params = argument.split(",");
for (String param : params) {
@@ -55,16 +53,16 @@ public class DebugAttachDetector {
try {
String[] address = param.split("=")[1].split(":");
if (address.length == 1) {
myPort = Integer.parseInt(address[0]);
port = Integer.parseInt(address[0]);
}
else {
myHost = address[0];
myPort = Integer.parseInt(address[1]);
host = address[0];
port = Integer.parseInt(address[1]);
}
}
catch (Exception e) {
LOG.error(e);
return;
return null;
}
break;
}
@@ -72,8 +70,23 @@ public class DebugAttachDetector {
break;
}
}
if (port > -1) {
return Pair.create(host, port);
}
return null;
}
if (myPort < 0) return;
public DebugAttachDetector() {
ApplicationEx app = ApplicationManagerEx.getApplicationEx();
if (!app.isInternal()
|| app.isUnitTestMode()
|| app.isHeadlessEnvironment()
|| "true".equals(System.getProperty("idea.debug.mode"))) return;
Pair<String, Integer> attachAddress = getAttachAddress(ManagementFactory.getRuntimeMXBean().getInputArguments());
if (attachAddress == null) return;
myHost = attachAddress.first;
myPort = attachAddress.second;
myTask = JobScheduler.getScheduler().scheduleWithFixedDelay(() -> {
boolean attached = !NetUtils.canConnectToRemoteSocket(myHost, myPort);
+1
View File
@@ -1610,6 +1610,7 @@
<xdebugger.debuggerSupport implementation="com.intellij.debugger.ui.JavaDebuggerSupport"/>
<xdebugger.settings implementation="com.intellij.debugger.settings.JavaDebuggerSettings"/>
<xdebugger.localAttachDebuggerProvider implementation="com.intellij.debugger.engine.JavaAttachDebuggerProvider"/>
<xdebugger.breakpointType implementation="com.intellij.debugger.ui.breakpoints.JavaMethodBreakpointType"/>
<xdebugger.breakpointType implementation="com.intellij.debugger.ui.breakpoints.JavaWildcardMethodBreakpointType"/>