d69ee8dc470f0f38290dd715196f027516106209
[idea/community.git] / java / debugger / impl / src / com / intellij / debugger / impl / GenericDebuggerRunner.java
1 /*
2  * Copyright 2000-2015 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.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;
45
46 public class GenericDebuggerRunner extends JavaPatchableProgramRunner<GenericDebuggerRunnerSettings> {
47   @Override
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);
51   }
52
53   @Override
54   @NotNull
55   public String getRunnerId() {
56     return DebuggingRunnerData.DEBUGGER_RUNNER_ID;
57   }
58
59   @Override
60   protected RunContentDescriptor doExecute(@NotNull RunProfileState state, @NotNull ExecutionEnvironment env) throws ExecutionException {
61     FileDocumentManager.getInstance().saveAllDocuments();
62     return createContentDescriptor(state, env);
63   }
64
65   @Nullable
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);
72     }
73     if (state instanceof PatchedRunnableState) {
74       final RemoteConnection connection = doPatch(new JavaParameters(), environment.getRunnerSettings());
75       return attachVirtualMachine(state, environment, connection, true);
76     }
77     if (state instanceof RemoteState) {
78       final RemoteConnection connection = createRemoteDebugConnection((RemoteState)state, environment.getRunnerSettings());
79       return attachVirtualMachine(state, environment, connection, false);
80     }
81
82     return null;
83   }
84
85   @Nullable
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) {
93       return null;
94     }
95
96     final DebugProcessImpl debugProcess = debuggerSession.getProcess();
97     if (debugProcess.isDetached() || debugProcess.isDetaching()) {
98       debuggerSession.dispose();
99       return null;
100     }
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);
105     }
106
107     return XDebuggerManager.getInstance(env.getProject()).startSession(env, new XDebugProcessStarter() {
108       @Override
109       @NotNull
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());
117         }
118         return JavaDebugProcess.create(session, debuggerSession);
119       }
120     }).getRunContentDescriptor();
121   }
122
123   private static RemoteConnection createRemoteDebugConnection(RemoteState connection, final RunnerSettings settings) {
124     final RemoteConnection remoteConnection = connection.getRemoteConnection();
125
126     GenericDebuggerRunnerSettings debuggerRunnerSettings = (GenericDebuggerRunnerSettings)settings;
127
128     if (debuggerRunnerSettings != null) {
129       remoteConnection.setUseSockets(debuggerRunnerSettings.getTransport() == DebuggerSettings.SOCKET_TRANSPORT);
130       remoteConnection.setAddress(debuggerRunnerSettings.getDebugPort());
131     }
132
133     return remoteConnection;
134   }
135
136   @Override
137   public GenericDebuggerRunnerSettings createConfigurationData(ConfigurationInfoProvider settingsProvider) {
138     return new GenericDebuggerRunnerSettings();
139   }
140
141   @Override
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);
145   }
146
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));
151     }
152     return DebuggerManagerImpl.createDebugParameters(javaParameters, debuggerSettings, false);
153   }
154
155   @Override
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());
160       }
161     }
162     return null;
163   }
164 }