blob: c6491a2b8a3fbed0d5600c488322b4ac18a4113c [file] [log] [blame]
/*
* Copyright 2000-2009 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.impl;
import com.intellij.debugger.DebugEnvironment;
import com.intellij.debugger.DebuggerManagerEx;
import com.intellij.debugger.DefaultDebugUIEnvironment;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.engine.JavaDebugProcess;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.debugger.ui.tree.render.BatchEvaluator;
import com.intellij.execution.DefaultExecutionResult;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.JavaPatchableProgramRunner;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
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.impl.XDebugSessionImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class GenericDebuggerRunner extends JavaPatchableProgramRunner<GenericDebuggerRunnerSettings> {
@Override
public boolean canRun(@NotNull final String executorId, @NotNull final RunProfile profile) {
return executorId.equals(DefaultDebugExecutor.EXECUTOR_ID) && profile instanceof ModuleRunProfile
&& !(profile instanceof RunConfigurationWithSuppressedDefaultDebugAction);
}
@Override
@NotNull
public String getRunnerId() {
return DebuggingRunnerData.DEBUGGER_RUNNER_ID;
}
@Override
protected RunContentDescriptor doExecute(@NotNull Project project,
@NotNull RunProfileState state,
@Nullable RunContentDescriptor contentToReuse,
@NotNull ExecutionEnvironment env) throws ExecutionException {
FileDocumentManager.getInstance().saveAllDocuments();
return createContentDescriptor(state, contentToReuse == null || env.getContentToReuse() == contentToReuse
? env
: new ExecutionEnvironmentBuilder(env).contentToReuse(contentToReuse).build());
}
@Nullable
protected RunContentDescriptor createContentDescriptor(@NotNull RunProfileState state, @NotNull ExecutionEnvironment environment) throws ExecutionException {
if (state instanceof JavaCommandLine) {
final JavaParameters parameters = ((JavaCommandLine)state).getJavaParameters();
runCustomPatchers(parameters, environment.getExecutor(), environment.getRunProfile());
RemoteConnection connection = DebuggerManagerImpl.createDebugParameters(parameters, true, DebuggerSettings.getInstance().DEBUGGER_TRANSPORT, "", false);
return attachVirtualMachine(state, environment, connection, true);
}
if (state instanceof PatchedRunnableState) {
final RemoteConnection connection = doPatch(new JavaParameters(), environment.getRunnerSettings());
return attachVirtualMachine(state, environment, connection, true);
}
if (state instanceof RemoteState) {
final RemoteConnection connection = createRemoteDebugConnection((RemoteState)state, environment.getRunnerSettings());
return attachVirtualMachine(state, environment, connection, false);
}
return null;
}
@Nullable
protected RunContentDescriptor attachVirtualMachine(RunProfileState state,
@NotNull ExecutionEnvironment env,
RemoteConnection connection,
boolean pollConnection) throws ExecutionException {
DebugEnvironment environment = new DefaultDebugUIEnvironment(env, state, connection, pollConnection).getEnvironment();
final DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(env.getProject()).attachVirtualMachine(environment);
if (debuggerSession == null) {
return null;
}
final DebugProcessImpl debugProcess = debuggerSession.getProcess();
if (debugProcess.isDetached() || debugProcess.isDetaching()) {
debuggerSession.dispose();
return null;
}
if (environment.isRemote()) {
// optimization: that way BatchEvaluator will not try to lookup the class file in remote VM
// which is an expensive operation when executed first time
debugProcess.putUserData(BatchEvaluator.REMOTE_SESSION_KEY, Boolean.TRUE);
}
return XDebuggerManager.getInstance(env.getProject()).startSession(env, new XDebugProcessStarter() {
@Override
@NotNull
public XDebugProcess start(@NotNull XDebugSession session) {
XDebugSessionImpl sessionImpl = (XDebugSessionImpl)session;
ExecutionResult executionResult = debugProcess.getExecutionResult();
sessionImpl.addExtraActions(executionResult.getActions());
if (executionResult instanceof DefaultExecutionResult) {
sessionImpl.addRestartActions(((DefaultExecutionResult)executionResult).getRestartActions());
sessionImpl.addExtraStopActions(((DefaultExecutionResult)executionResult).getAdditionalStopActions());
}
return new JavaDebugProcess(session, debuggerSession);
}
}).getRunContentDescriptor();
}
private static RemoteConnection createRemoteDebugConnection(RemoteState connection, final RunnerSettings settings) {
final RemoteConnection remoteConnection = connection.getRemoteConnection();
GenericDebuggerRunnerSettings debuggerRunnerSettings = (GenericDebuggerRunnerSettings)settings;
if (debuggerRunnerSettings != null) {
remoteConnection.setUseSockets(debuggerRunnerSettings.getTransport() == DebuggerSettings.SOCKET_TRANSPORT);
remoteConnection.setAddress(debuggerRunnerSettings.DEBUG_PORT);
}
return remoteConnection;
}
@Override
public GenericDebuggerRunnerSettings createConfigurationData(ConfigurationInfoProvider settingsProvider) {
return new GenericDebuggerRunnerSettings();
}
@Override
public void patch(JavaParameters javaParameters, RunnerSettings settings, RunProfile runProfile, final boolean beforeExecution) throws ExecutionException {
doPatch(javaParameters, settings);
runCustomPatchers(javaParameters, Executor.EXECUTOR_EXTENSION_NAME.findExtension(DefaultDebugExecutor.class), runProfile);
}
private static RemoteConnection doPatch(final JavaParameters javaParameters, final RunnerSettings settings) throws ExecutionException {
final GenericDebuggerRunnerSettings debuggerSettings = ((GenericDebuggerRunnerSettings)settings);
if (StringUtil.isEmpty(debuggerSettings.getDebugPort())) {
debuggerSettings.setDebugPort(DebuggerUtils.getInstance().findAvailableDebugAddress(debuggerSettings.getTransport() == DebuggerSettings.SOCKET_TRANSPORT));
}
return DebuggerManagerImpl.createDebugParameters(javaParameters, debuggerSettings, false);
}
@Override
public SettingsEditor<GenericDebuggerRunnerSettings> getSettingsEditor(final Executor executor, RunConfiguration configuration) {
if (configuration instanceof RunConfigurationWithRunnerSettings) {
if (((RunConfigurationWithRunnerSettings)configuration).isSettingsNeeded()) {
return new GenericDebuggerParametersRunnerConfigurable(configuration.getProject());
}
}
return null;
}
}