9ba4a3d4746f6d5b78b22ea3341653b0d4305e1c
[idea/community.git] / java / debugger / impl / src / com / intellij / debugger / impl / GenericDebuggerRunner.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.debugger.impl;
17
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.execution.DefaultExecutionResult;
26 import com.intellij.execution.ExecutionException;
27 import com.intellij.execution.ExecutionResult;
28 import com.intellij.execution.Executor;
29 import com.intellij.execution.configurations.*;
30 import com.intellij.execution.executors.DefaultDebugExecutor;
31 import com.intellij.execution.runners.ExecutionEnvironment;
32 import com.intellij.execution.runners.JavaPatchableProgramRunner;
33 import com.intellij.execution.ui.RunContentDescriptor;
34 import com.intellij.openapi.fileEditor.FileDocumentManager;
35 import com.intellij.openapi.options.SettingsEditor;
36 import com.intellij.openapi.util.text.StringUtil;
37 import com.intellij.xdebugger.XDebugProcess;
38 import com.intellij.xdebugger.XDebugProcessStarter;
39 import com.intellij.xdebugger.XDebugSession;
40 import com.intellij.xdebugger.XDebuggerManager;
41 import com.intellij.xdebugger.impl.XDebugSessionImpl;
42 import org.jetbrains.annotations.NotNull;
43 import org.jetbrains.annotations.Nullable;
44
45 public class GenericDebuggerRunner extends JavaPatchableProgramRunner<GenericDebuggerRunnerSettings> {
46   @Override
47   public boolean canRun(@NotNull final String executorId, @NotNull final RunProfile profile) {
48     return executorId.equals(DefaultDebugExecutor.EXECUTOR_ID) && profile instanceof ModuleRunProfile
49            && !(profile instanceof RunConfigurationWithSuppressedDefaultDebugAction);
50   }
51
52   @Override
53   @NotNull
54   public String getRunnerId() {
55     return DebuggingRunnerData.DEBUGGER_RUNNER_ID;
56   }
57
58   @Override
59   protected RunContentDescriptor doExecute(@NotNull RunProfileState state, @NotNull ExecutionEnvironment env) throws ExecutionException {
60     FileDocumentManager.getInstance().saveAllDocuments();
61     return createContentDescriptor(state, env);
62   }
63
64   @Nullable
65   protected RunContentDescriptor createContentDescriptor(@NotNull RunProfileState state, @NotNull ExecutionEnvironment environment) throws ExecutionException {
66     if (state instanceof JavaCommandLine) {
67       final JavaParameters parameters = ((JavaCommandLine)state).getJavaParameters();
68       runCustomPatchers(parameters, environment.getExecutor(), environment.getRunProfile());
69       RemoteConnection connection = DebuggerManagerImpl.createDebugParameters(parameters, true, DebuggerSettings.getInstance().DEBUGGER_TRANSPORT, "", false);
70       return attachVirtualMachine(state, environment, connection, true);
71     }
72     if (state instanceof PatchedRunnableState) {
73       final RemoteConnection connection = doPatch(new JavaParameters(), environment.getRunnerSettings());
74       return attachVirtualMachine(state, environment, connection, true);
75     }
76     if (state instanceof RemoteState) {
77       final RemoteConnection connection = createRemoteDebugConnection((RemoteState)state, environment.getRunnerSettings());
78       return attachVirtualMachine(state, environment, connection, false);
79     }
80
81     return null;
82   }
83
84   @Nullable
85   protected RunContentDescriptor attachVirtualMachine(RunProfileState state,
86                                                       @NotNull ExecutionEnvironment env,
87                                                       RemoteConnection connection,
88                                                       boolean pollConnection) throws ExecutionException {
89     DebugEnvironment environment = new DefaultDebugEnvironment(env, state, connection, pollConnection);
90     final DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(env.getProject()).attachVirtualMachine(environment);
91     if (debuggerSession == null) {
92       return null;
93     }
94
95     final DebugProcessImpl debugProcess = debuggerSession.getProcess();
96
97     return XDebuggerManager.getInstance(env.getProject()).startSession(env, new XDebugProcessStarter() {
98       @Override
99       @NotNull
100       public XDebugProcess start(@NotNull XDebugSession session) {
101         XDebugSessionImpl sessionImpl = (XDebugSessionImpl)session;
102         ExecutionResult executionResult = debugProcess.getExecutionResult();
103         sessionImpl.addExtraActions(executionResult.getActions());
104         if (executionResult instanceof DefaultExecutionResult) {
105           sessionImpl.addRestartActions(((DefaultExecutionResult)executionResult).getRestartActions());
106           sessionImpl.addExtraStopActions(((DefaultExecutionResult)executionResult).getAdditionalStopActions());
107         }
108         return JavaDebugProcess.create(session, debuggerSession);
109       }
110     }).getRunContentDescriptor();
111   }
112
113   private static RemoteConnection createRemoteDebugConnection(RemoteState connection, final RunnerSettings settings) {
114     final RemoteConnection remoteConnection = connection.getRemoteConnection();
115
116     GenericDebuggerRunnerSettings debuggerRunnerSettings = (GenericDebuggerRunnerSettings)settings;
117
118     if (debuggerRunnerSettings != null) {
119       remoteConnection.setUseSockets(debuggerRunnerSettings.getTransport() == DebuggerSettings.SOCKET_TRANSPORT);
120       remoteConnection.setAddress(debuggerRunnerSettings.getDebugPort());
121     }
122
123     return remoteConnection;
124   }
125
126   @Override
127   public GenericDebuggerRunnerSettings createConfigurationData(ConfigurationInfoProvider settingsProvider) {
128     return new GenericDebuggerRunnerSettings();
129   }
130
131   @Override
132   public void patch(JavaParameters javaParameters, RunnerSettings settings, RunProfile runProfile, final boolean beforeExecution) throws ExecutionException {
133     doPatch(javaParameters, settings);
134     runCustomPatchers(javaParameters, Executor.EXECUTOR_EXTENSION_NAME.findExtension(DefaultDebugExecutor.class), runProfile);
135   }
136
137   private static RemoteConnection doPatch(final JavaParameters javaParameters, final RunnerSettings settings) throws ExecutionException {
138     final GenericDebuggerRunnerSettings debuggerSettings = ((GenericDebuggerRunnerSettings)settings);
139     if (StringUtil.isEmpty(debuggerSettings.getDebugPort())) {
140       debuggerSettings.setDebugPort(DebuggerUtils.getInstance().findAvailableDebugAddress(debuggerSettings.getTransport() == DebuggerSettings.SOCKET_TRANSPORT));
141     }
142     return DebuggerManagerImpl.createDebugParameters(javaParameters, debuggerSettings, false);
143   }
144
145   @Override
146   public SettingsEditor<GenericDebuggerRunnerSettings> getSettingsEditor(final Executor executor, RunConfiguration configuration) {
147     if (configuration instanceof RunConfigurationWithRunnerSettings) {
148       if (((RunConfigurationWithRunnerSettings)configuration).isSettingsNeeded()) {
149         return new GenericDebuggerParametersRunnerConfigurable(configuration.getProject());
150       }
151     }
152     return null;
153   }
154 }