2 * Copyright 2000-2015 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.debugger.impl;
18 import com.intellij.debugger.DebugEnvironment;
19 import com.intellij.debugger.DebuggerManagerEx;
20 import com.intellij.debugger.DefaultDebugEnvironment;
21 import com.intellij.debugger.engine.DebugProcessImpl;
22 import com.intellij.debugger.engine.DebuggerUtils;
23 import com.intellij.debugger.engine.JavaDebugProcess;
24 import com.intellij.debugger.settings.DebuggerSettings;
25 import com.intellij.debugger.ui.tree.render.BatchEvaluator;
26 import com.intellij.execution.DefaultExecutionResult;
27 import com.intellij.execution.ExecutionException;
28 import com.intellij.execution.ExecutionResult;
29 import com.intellij.execution.Executor;
30 import com.intellij.execution.configurations.*;
31 import com.intellij.execution.executors.DefaultDebugExecutor;
32 import com.intellij.execution.runners.ExecutionEnvironment;
33 import com.intellij.execution.runners.JavaPatchableProgramRunner;
34 import com.intellij.execution.ui.RunContentDescriptor;
35 import com.intellij.openapi.fileEditor.FileDocumentManager;
36 import com.intellij.openapi.options.SettingsEditor;
37 import com.intellij.openapi.util.text.StringUtil;
38 import com.intellij.xdebugger.XDebugProcess;
39 import com.intellij.xdebugger.XDebugProcessStarter;
40 import com.intellij.xdebugger.XDebugSession;
41 import com.intellij.xdebugger.XDebuggerManager;
42 import com.intellij.xdebugger.impl.XDebugSessionImpl;
43 import org.jetbrains.annotations.NotNull;
44 import org.jetbrains.annotations.Nullable;
46 public class GenericDebuggerRunner extends JavaPatchableProgramRunner<GenericDebuggerRunnerSettings> {
48 public boolean canRun(@NotNull final String executorId, @NotNull final RunProfile profile) {
49 return executorId.equals(DefaultDebugExecutor.EXECUTOR_ID) && profile instanceof ModuleRunProfile
50 && !(profile instanceof RunConfigurationWithSuppressedDefaultDebugAction);
55 public String getRunnerId() {
56 return DebuggingRunnerData.DEBUGGER_RUNNER_ID;
60 protected RunContentDescriptor doExecute(@NotNull RunProfileState state, @NotNull ExecutionEnvironment env) throws ExecutionException {
61 FileDocumentManager.getInstance().saveAllDocuments();
62 return createContentDescriptor(state, env);
66 protected RunContentDescriptor createContentDescriptor(@NotNull RunProfileState state, @NotNull ExecutionEnvironment environment) throws ExecutionException {
67 if (state instanceof JavaCommandLine) {
68 final JavaParameters parameters = ((JavaCommandLine)state).getJavaParameters();
69 runCustomPatchers(parameters, environment.getExecutor(), environment.getRunProfile());
70 RemoteConnection connection = DebuggerManagerImpl.createDebugParameters(parameters, true, DebuggerSettings.getInstance().DEBUGGER_TRANSPORT, "", false);
71 return attachVirtualMachine(state, environment, connection, true);
73 if (state instanceof PatchedRunnableState) {
74 final RemoteConnection connection = doPatch(new JavaParameters(), environment.getRunnerSettings());
75 return attachVirtualMachine(state, environment, connection, true);
77 if (state instanceof RemoteState) {
78 final RemoteConnection connection = createRemoteDebugConnection((RemoteState)state, environment.getRunnerSettings());
79 return attachVirtualMachine(state, environment, connection, false);
86 protected RunContentDescriptor attachVirtualMachine(RunProfileState state,
87 @NotNull ExecutionEnvironment env,
88 RemoteConnection connection,
89 boolean pollConnection) throws ExecutionException {
90 DebugEnvironment environment = new DefaultDebugEnvironment(env, state, connection, pollConnection);
91 final DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(env.getProject()).attachVirtualMachine(environment);
92 if (debuggerSession == null) {
96 final DebugProcessImpl debugProcess = debuggerSession.getProcess();
97 if (debugProcess.isDetached() || debugProcess.isDetaching()) {
98 debuggerSession.dispose();
101 if (environment.isRemote()) {
102 // optimization: that way BatchEvaluator will not try to lookup the class file in remote VM
103 // which is an expensive operation when executed first time
104 debugProcess.putUserData(BatchEvaluator.REMOTE_SESSION_KEY, Boolean.TRUE);
107 return XDebuggerManager.getInstance(env.getProject()).startSession(env, new XDebugProcessStarter() {
110 public XDebugProcess start(@NotNull XDebugSession session) {
111 XDebugSessionImpl sessionImpl = (XDebugSessionImpl)session;
112 ExecutionResult executionResult = debugProcess.getExecutionResult();
113 sessionImpl.addExtraActions(executionResult.getActions());
114 if (executionResult instanceof DefaultExecutionResult) {
115 sessionImpl.addRestartActions(((DefaultExecutionResult)executionResult).getRestartActions());
116 sessionImpl.addExtraStopActions(((DefaultExecutionResult)executionResult).getAdditionalStopActions());
118 return JavaDebugProcess.create(session, debuggerSession);
120 }).getRunContentDescriptor();
123 private static RemoteConnection createRemoteDebugConnection(RemoteState connection, final RunnerSettings settings) {
124 final RemoteConnection remoteConnection = connection.getRemoteConnection();
126 GenericDebuggerRunnerSettings debuggerRunnerSettings = (GenericDebuggerRunnerSettings)settings;
128 if (debuggerRunnerSettings != null) {
129 remoteConnection.setUseSockets(debuggerRunnerSettings.getTransport() == DebuggerSettings.SOCKET_TRANSPORT);
130 remoteConnection.setAddress(debuggerRunnerSettings.getDebugPort());
133 return remoteConnection;
137 public GenericDebuggerRunnerSettings createConfigurationData(ConfigurationInfoProvider settingsProvider) {
138 return new GenericDebuggerRunnerSettings();
142 public void patch(JavaParameters javaParameters, RunnerSettings settings, RunProfile runProfile, final boolean beforeExecution) throws ExecutionException {
143 doPatch(javaParameters, settings);
144 runCustomPatchers(javaParameters, Executor.EXECUTOR_EXTENSION_NAME.findExtension(DefaultDebugExecutor.class), runProfile);
147 private static RemoteConnection doPatch(final JavaParameters javaParameters, final RunnerSettings settings) throws ExecutionException {
148 final GenericDebuggerRunnerSettings debuggerSettings = ((GenericDebuggerRunnerSettings)settings);
149 if (StringUtil.isEmpty(debuggerSettings.getDebugPort())) {
150 debuggerSettings.setDebugPort(DebuggerUtils.getInstance().findAvailableDebugAddress(debuggerSettings.getTransport() == DebuggerSettings.SOCKET_TRANSPORT));
152 return DebuggerManagerImpl.createDebugParameters(javaParameters, debuggerSettings, false);
156 public SettingsEditor<GenericDebuggerRunnerSettings> getSettingsEditor(final Executor executor, RunConfiguration configuration) {
157 if (configuration instanceof RunConfigurationWithRunnerSettings) {
158 if (((RunConfigurationWithRunnerSettings)configuration).isSettingsNeeded()) {
159 return new GenericDebuggerParametersRunnerConfigurable(configuration.getProject());