| /* |
| * 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; |
| } |
| } |