package org.eclipse.dltk.launching;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.dltk.core.IPreferencesLookupDelegate;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.PreferencesLookupDelegate;
import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.dltk.core.environment.IEnvironment;
import org.eclipse.dltk.dbgp.DbgpSessionIdGenerator;
import org.eclipse.dltk.debug.core.DLTKDebugPlugin;
import org.eclipse.dltk.debug.core.DLTKDebugPreferenceConstants;
import org.eclipse.dltk.debug.core.ExtendedDebugEventDetails;
import org.eclipse.dltk.debug.core.IDbgpService;
import org.eclipse.dltk.debug.core.ScriptDebugManager;
import org.eclipse.dltk.debug.core.model.IScriptDebugTarget;
import org.eclipse.dltk.debug.core.model.IScriptDebugThreadConfigurator;
import org.eclipse.dltk.internal.debug.core.model.DebugEventHelper;
import org.eclipse.dltk.internal.debug.core.model.ScriptDebugTarget;
import org.eclipse.dltk.internal.launching.InterpreterMessages;
import org.eclipse.dltk.internal.launching.LaunchConfigurationUtils;
import org.eclipse.dltk.launching.debug.DbgpConnectionConfig;
import org.eclipse.dltk.launching.debug.DebuggingEngineManager;
import org.eclipse.dltk.launching.debug.IDebuggingEngine;
import org.eclipse.dltk.launching.process.ScriptRuntimeProcessFactory;
public abstract class DebuggingEngineRunner extends AbstractInterpreterRunner {
// Launch attributes
public static final String LAUNCH_ATTR_DEBUGGING_ENGINE_ID = "debugging_engine_id"; //$NON-NLS-1$
public static final String OVERRIDE_EXE = "OVERRIDE_EXE"; //$NON-NLS-1$
protected String getSessionId(ILaunchConfiguration configuration)
throws CoreException {
return DbgpSessionIdGenerator.generate();
}
@Deprecated
protected final IScriptDebugTarget addDebugTarget(ILaunch launch,
IDbgpService dbgpService) throws CoreException {
return null;
}
protected IScriptDebugTarget createDebugTarget(ILaunch launch,
IDbgpService dbgpService) throws CoreException {
return new ScriptDebugTarget(getDebugModelId(), dbgpService,
getSessionId(launch.getLaunchConfiguration()), launch, null);
}
public DebuggingEngineRunner(IInterpreterInstall install) {
super(install);
}
protected void initializeLaunch(ILaunch launch, InterpreterConfig config,
PreferencesLookupDelegate delegate) throws CoreException {
final IDbgpService service = DLTKDebugPlugin.getDefault()
.getDbgpService();
if (!service.available()) {
abort(InterpreterMessages.errDbgpServiceNotAvailable, null);
}
final IScriptDebugTarget target = createDebugTarget(launch, service);
launch.addDebugTarget(target);
IScriptDebugThreadConfigurator configurator = createThreadConfigurator(
launch
.getLaunchConfiguration());
if (configurator != null) {
((ScriptDebugTarget) target)
.setScriptDebugThreadConfigurator(configurator);
}
String qualifier = getDebugPreferenceQualifier();
target.toggleGlobalVariables(delegate.getBoolean(qualifier,
showGlobalVarsPreferenceKey()));
target.toggleClassVariables(delegate.getBoolean(qualifier,
showClassVarsPreferenceKey()));
target.toggleLocalVariables(delegate.getBoolean(qualifier,
showLocalVarsPreferenceKey()));
// Debugging engine id
launch.setAttribute(LAUNCH_ATTR_DEBUGGING_ENGINE_ID,
getDebuggingEngineId());
// Configuration
DbgpConnectionConfig.save(config, getBindAddress(), service.getPort(),
target.getSessionId());
}
private String getBindAddress() {
return DLTKDebugPlugin.getDefault().getBindAddress();
}
/**
* @see #addEngineConfig(InterpreterConfig,PreferencesLookupDelegate,ILaunch)
*/
@Deprecated
protected final InterpreterConfig addEngineConfig(InterpreterConfig config,
PreferencesLookupDelegate delegate) {
return null;
}
/**
* Add the debugging engine configuration.
*
* @param launch
*/
protected abstract InterpreterConfig addEngineConfig(
InterpreterConfig config, PreferencesLookupDelegate delegate,
ILaunch launch) throws CoreException;
@Override
public void run(InterpreterConfig config, ILaunch launch,
IProgressMonitor monitor) throws CoreException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
monitor.beginTask(InterpreterMessages.DebuggingEngineRunner_launching,
4);
if (monitor.isCanceled()) {
return;
}
try {
PreferencesLookupDelegate delegate = createPreferencesLookupDelegate(
launch);
initializeLaunch(launch, config, delegate);
final ScriptDebugTarget target = (ScriptDebugTarget) launch
.getDebugTarget();
final DebugSessionAcceptor acceptor = new DebugSessionAcceptor(
target, monitor);
try {
monitor.worked(1);
target.setProcess(startProcess(config, launch, monitor,
delegate));
monitor.worked(1);
// Waiting for debugging engine to connect
waitDebuggerConnected(launch, acceptor);
} finally {
acceptor.disposeStatusHandler();
}
} catch (CoreException e) {
launch.terminate();
throw e;
} finally {
monitor.done();
}
// Happy debugging :)
}
protected IProcess startProcess(InterpreterConfig config, ILaunch launch,
IProgressMonitor monitor, PreferencesLookupDelegate delegate)
throws CoreException {
InterpreterConfig newConfig = addEngineConfig(config, delegate, launch);
// Starting debugging engine
IProcess process = null;
try {
DebugEventHelper.fireExtendedEvent(newConfig,
ExtendedDebugEventDetails.BEFORE_VM_STARTED);
// Running
monitor.subTask(InterpreterMessages.DebuggingEngineRunner_running);
process = rawRun(launch, newConfig);
} catch (CoreException e) {
abort(InterpreterMessages.errDebuggingEngineNotStarted, e);
}
return process;
}
@Override
protected String[] renderCommandLine(InterpreterConfig config) {
String exe = (String) config.getProperty(OVERRIDE_EXE);
if (exe != null) {
return config.renderCommandLine(getInstall().getEnvironment(), exe);
}
return config.renderCommandLine(getInstall());
}
/**
* Used to create new script thread configurator.
*
* @return
*/
@Deprecated
protected final IScriptDebugThreadConfigurator createThreadConfigurator() {
return null;
}
/**
* Used to create new script thread configurator.
*
* @param configuration
*/
protected IScriptDebugThreadConfigurator createThreadConfigurator(
ILaunchConfiguration configuration) {
return null;
}
/**
* @param process
* @param launch
* @param monitor
* @throws CoreException
*/
@Deprecated
protected void waitDebuggerConnected(IProcess process, ILaunch launch,
IProgressMonitor monitor) throws CoreException {
ScriptDebugTarget target = (ScriptDebugTarget) launch.getDebugTarget();
waitDebuggerConnected(launch,
new DebugSessionAcceptor(target, monitor));
}
/**
* Waiting debugging process to connect to current launch
*
* @param launch
* launch to connect to
* @param acceptor
* @param monitor
* progress monitor
* @throws CoreException
* if debuggingProcess terminated, monitor is canceled or // *
* timeout
*/
protected void waitDebuggerConnected(ILaunch launch,
DebugSessionAcceptor acceptor) throws CoreException {
ILaunchConfiguration configuration = launch.getLaunchConfiguration();
int timeout = LaunchConfigurationUtils.getConnectionTimeout(
configuration, DLTKDebugPlugin.getConnectionTimeout());
if (!acceptor.waitConnection(timeout)) {
launch.terminate();
return;
// abort(InterpreterMessages.errDebuggingEngineNotConnected, null);
}
if (!acceptor.waitInitialized(60 * 60 * 1000)) {
launch.terminate();
abort(InterpreterMessages.errDebuggingEngineNotInitialized, null);
}
}
public String getDebugModelId() {
return ScriptDebugManager.getInstance().getDebugModelByNature(
getInstall().getNatureId());
}
public IDebuggingEngine getDebuggingEngine() {
return DebuggingEngineManager.getInstance().getDebuggingEngine(
getDebuggingEngineId());
}
protected String showGlobalVarsPreferenceKey() {
return DLTKDebugPreferenceConstants.PREF_DBGP_SHOW_SCOPE_GLOBAL;
}
protected String showClassVarsPreferenceKey() {
return DLTKDebugPreferenceConstants.PREF_DBGP_SHOW_SCOPE_CLASS;
}
protected String showLocalVarsPreferenceKey() {
return DLTKDebugPreferenceConstants.PREF_DBGP_SHOW_SCOPE_LOCAL;
}
protected abstract String getDebuggingEngineId();
protected PreferencesLookupDelegate createPreferencesLookupDelegate(
ILaunch launch) throws CoreException {
IScriptProject sProject = ScriptRuntime.getScriptProject(launch
.getLaunchConfiguration());
return new PreferencesLookupDelegate(
sProject == null ? null : sProject.getProject());
}
/**
* Returns the id of the plugin whose preference store contains general
* debugging preference settings.
*/
protected abstract String getDebugPreferenceQualifier();
/**
* Returns the id of the plugin whose preference store contains debugging
* engine preferences.
*/
protected abstract String getDebuggingEnginePreferenceQualifier();
/**
* Tests if logging is enabled for this engine.
*
* <p>
* Note: this method controls logging for the actual debugging engine, and
* not the DBGP protocol output.
* </p>
*/
protected boolean isLoggingEnabled(IPreferencesLookupDelegate delegate) {
return true;
}
/**
* Returns the preference key usd to store the log file name
*/
protected abstract String getLogFileNamePreferenceKey();
/**
* Returns a fully qualified path to a log file name or <code>null</code> if
* logging is not enabled.
*/
protected String getLogFileName(PreferencesLookupDelegate delegate,
String sessionId) {
if (!isLoggingEnabled(delegate)) {
return null;
}
String qualifier = getDebuggingEnginePreferenceQualifier();
String keyValue = delegate.getString(qualifier,
getLogFileNamePreferenceKey());
Map<IEnvironment, String> logFileNames = EnvironmentPathUtils
.decodePaths(keyValue);
IEnvironment env = getInstall().getEnvironment();
String pathString = logFileNames.get(env);
if (pathString != null && pathString.length() > 0) {
return pathString;
} else {
return null;
}
}
private String getProcessFactoryId(ILaunch launch) {
final ILaunchConfiguration config = launch.getLaunchConfiguration();
if (config != null) {
try {
return config.getAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID,
(String) null);
} catch (CoreException e) {
}
}
return null;
}
@Override
protected IProcess newProcess(ILaunch launch, Process p, String label,
Map<String, String> attributes) throws CoreException {
if (getProcessFactoryId(launch) == null
&& ScriptRuntimeProcessFactory.isSupported(launch)) {
/*
* Process factory not specified, but it should be.
*/
return new ScriptRuntimeProcessFactory().newProcess(launch, p,
label, attributes);
}
return super.newProcess(launch, p, label, attributes);
}
}