/* * Copyright 2013-2017 Grzegorz Ligas <ligasgr@gmail.com> and other contributors * (see the CONTRIBUTORS file). * * 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 org.intellij.xquery.debugger; import com.codnos.dbgp.api.DBGpIde; import com.intellij.execution.ExecutionException; import com.intellij.execution.ExecutionResult; import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.configurations.RunProfileState; import com.intellij.execution.executors.DefaultDebugExecutor; import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.runners.DefaultProgramRunner; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.util.net.NetUtils; import com.intellij.xdebugger.XDebugProcess; import com.intellij.xdebugger.XDebugProcessStarter; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerManager; import org.intellij.xquery.runner.XQueryRunProfileState; import org.intellij.xquery.runner.rt.XQueryDataSourceType; import org.intellij.xquery.runner.state.run.XQueryRunConfiguration; import org.jetbrains.annotations.NotNull; import static com.codnos.dbgp.api.DBGpFactory.ide; public class XQueryDebuggerRunner extends DefaultProgramRunner { private static final String XQUERY_RUNNER_ID = "XQueryDebuggerRunner"; @NotNull @Override public String getRunnerId() { return XQUERY_RUNNER_ID; } @Override public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) { return DefaultDebugExecutor.EXECUTOR_ID.equals(executorId) && profile instanceof XQueryRunConfiguration && isDebugSupportedFor((XQueryRunConfiguration) profile); } private boolean isDebugSupportedFor(XQueryRunConfiguration profile) { XQueryDataSourceType dataSourceType = profile.getDataSourceType(); return dataSourceType != null && dataSourceType.isDebugSupported(); } @Override protected RunContentDescriptor doExecute(@NotNull RunProfileState state, @NotNull ExecutionEnvironment env) throws ExecutionException { return createContentDescriptor(state, env); } private RunContentDescriptor createContentDescriptor(final RunProfileState runProfileState, final ExecutionEnvironment environment) throws ExecutionException { XDebuggerManager debuggerManager = XDebuggerManager.getInstance(environment.getProject()); XDebugProcessStarter processStarter = getProcessStarter(runProfileState, environment); final XDebugSession debugSession = debuggerManager.startSession(environment, processStarter); return debugSession.getRunContentDescriptor(); } private int getAvailablePort() { return NetUtils.tryToFindAvailableSocketPort(9000); } private XDebugProcessStarter getProcessStarter(final RunProfileState runProfileState, final ExecutionEnvironment executionEnvironment) throws ExecutionException { int port = getAvailablePort(); ((XQueryRunProfileState) runProfileState).setPort(port); return new XDebugProcessStarter() { @NotNull public XDebugProcess start(@NotNull final XDebugSession session) throws ExecutionException { final ExecutionResult result = runProfileState.execute(executionEnvironment.getExecutor(), XQueryDebuggerRunner.this); XQueryDebugProcess.XQueryDebuggerIde debuggerIde = new XQueryDebugProcess.XQueryDebuggerIde(session, result.getProcessHandler()); final DBGpIde dbgpIde = ide().withPort(port).withDebuggerIde(debuggerIde).build(); dbgpIde.startListening(); result.getProcessHandler().addProcessListener(new ProcessAdapter() { @Override public void processTerminated(ProcessEvent event) { dbgpIde.stopListening(); } }); return new XQueryDebugProcess(session, result, dbgpIde); } }; } }