/******************************************************************************* * Copyright (c) 2008 xored software, Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * xored software, Inc. - initial API and Implementation (Andrei Sobolev) *******************************************************************************/ package org.eclipse.dltk.tcl.activestatedebugger; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.dltk.compiler.util.Util; import org.eclipse.dltk.core.IPreferencesLookupDelegate; import org.eclipse.dltk.core.IScriptProject; import org.eclipse.dltk.core.environment.EnvironmentManager; import org.eclipse.dltk.core.environment.IEnvironment; import org.eclipse.dltk.dbgp.IDbgpFeature; import org.eclipse.dltk.dbgp.IDbgpSpawnpoint; import org.eclipse.dltk.dbgp.commands.IDbgpSpawnpointCommands; import org.eclipse.dltk.dbgp.exceptions.DbgpException; import org.eclipse.dltk.debug.core.model.IScriptBreakpointPathMapper; import org.eclipse.dltk.debug.core.model.IScriptDebugTarget; import org.eclipse.dltk.debug.core.model.IScriptDebugThreadConfigurator; import org.eclipse.dltk.debug.core.model.IScriptThread; import org.eclipse.dltk.internal.debug.core.model.ScriptLineBreakpoint; import org.eclipse.dltk.internal.debug.core.model.ScriptThread; import org.eclipse.dltk.internal.debug.core.model.operations.DbgpDebugger; import org.eclipse.dltk.launching.IInterpreterInstall; import org.eclipse.dltk.launching.ScriptRuntime; import org.eclipse.dltk.tcl.activestatedebugger.InstrumentationSetup.PatternEntry; import org.eclipse.dltk.tcl.activestatedebugger.preferences.InstrumentationConfig; import org.eclipse.dltk.tcl.activestatedebugger.preferences.PatternListIO; public class TclActiveStateDebugThreadConfigurator implements IScriptDebugThreadConfigurator { private boolean initialized = false; private final IScriptProject project; private final IPreferencesLookupDelegate delegate; /** * @param project * @param delegate */ public TclActiveStateDebugThreadConfigurator(IScriptProject project, IPreferencesLookupDelegate delegate) { this.project = project; this.delegate = delegate; } public void configureThread(DbgpDebugger engine, ScriptThread scriptThread) { if (initialized) { return; } initialized = true; try { IDbgpFeature tclFeature = engine.getFeature("tcl_instrument_set"); //$NON-NLS-1$ if (tclFeature.isSupported()) { ActiveStateInstrumentCommands commands = new ActiveStateInstrumentCommands( engine.getSession().getCommunicator()); final ILaunchConfiguration launchConf = scriptThread .getLaunch().getLaunchConfiguration(); if (launchConf != null) { final IInterpreterInstall install = ScriptRuntime .computeInterpreterInstall(launchConf); if (install != null) { initializeDebugger(commands, install); } } } } catch (DbgpException e) { TclActiveStateDebuggerPlugin.warn(e); } catch (CoreException e) { TclActiveStateDebuggerPlugin.warn(e); } } // private static abstract class PatternRef { // final boolean include; // // public PatternRef(boolean include) { // this.include = include; // } // // } // // private static class LibraryContainerRef extends PatternRef { // // public LibraryContainerRef(boolean include) { // super(include); // } // // } // // private static class ModelElementRef extends PatternRef { // final IModelElement element; // // public ModelElementRef(IModelElement element, boolean include) { // super(include); // this.element = element; // } // // } // private static List<PatternRef> parsePatterns(InstrumentationConfig // config) { // List<PatternRef> result = new ArrayList<PatternRef>(); // if (config != null) { // for (Pattern pattern : config.getModelElements()) { // if (pattern instanceof ModelElementPattern) { // final IModelElement element = DLTKCore // .create(((ModelElementPattern) pattern) // .getHandleIdentifier()); // if (element != null) { // result.add(new ModelElementRef(element, pattern // .isInclude())); // } // } else if (pattern instanceof LibraryPattern) { // result.add(new LibraryContainerRef(pattern.isInclude())); // } // } // } // return result; // } private void initializeDebugger(ActiveStateInstrumentCommands commands, IInterpreterInstall install) throws DbgpException { final Set<InstrumentationFeature> selectedFeatures = InstrumentationFeature .decode(getString(TclActiveStateDebuggerConstants.INSTRUMENTATION_FEATURES)); for (InstrumentationFeature feature : InstrumentationFeature.values()) { commands.instrumentSet(feature, selectedFeatures.contains(feature)); } final ErrorAction errorAction = ErrorAction .decode(getString(TclActiveStateDebuggerConstants.INSTRUMENTATION_ERROR_ACTION)); if (errorAction != null) { commands.setErrorAction(errorAction); } final InstrumentationConfig config = PatternListIO .decode(getString(TclActiveStateDebuggerConstants.INSTRUMENTATION_PATTERNS)); final InstrumentationConfigProcessor configurator = new InstrumentationConfigProcessor( project, install); configurator.configure(config); for (PatternEntry entry : configurator.getPatterns()) { if (entry.isInclude()) { commands.instrumentInclude(entry.getPatternText()); } else { commands.instrumentExclude(entry.getPatternText()); } } } private String getString(final String key) { return delegate.getString(TclActiveStateDebuggerPlugin.PLUGIN_ID, key); } private List<IMarker> loadSpawnpoints() throws CoreException { final IWorkspaceRoot root = InstrumentationUtils.getWorkspaceRoot(); final IMarker[] markers = root.findMarkers( TclActiveStateDebuggerConstants.SPAWNPOINT_MARKER_TYPE, true, IResource.DEPTH_INFINITE); if (markers.length == 0) { return Collections.emptyList(); } final IEnvironment environment = EnvironmentManager .getEnvironment(project); if (environment == null) { return Arrays.asList(markers); } final Map<IProject, Boolean> projectStatus = new HashMap<IProject, Boolean>(); final List<IMarker> result = new ArrayList<IMarker>(); for (IMarker marker : markers) { final IProject project = marker.getResource().getProject(); Boolean status = projectStatus.get(project); if (status == null) { if (environment.equals(EnvironmentManager .getEnvironment(project))) { status = Boolean.TRUE; } else { status = Boolean.FALSE; } projectStatus.put(project, status); } if (status.booleanValue()) { result.add(marker); } } return result; } public void initializeBreakpoints(IScriptThread thread, IProgressMonitor monitor) { try { final List<IMarker> spawnpoints = loadSpawnpoints(); monitor.beginTask(Util.EMPTY_STRING, spawnpoints.size()); final IDbgpSpawnpointCommands commands = (IDbgpSpawnpointCommands) thread .getDbgpSession().get(IDbgpSpawnpointCommands.class); final IScriptBreakpointPathMapper pathMapper = ((IScriptDebugTarget) thread .getDebugTarget()).getPathMapper(); for (final IMarker spawnpoint : spawnpoints) { final URI uri = ScriptLineBreakpoint.makeUri(new Path( spawnpoint.getResource().getLocationURI().getPath())); try { final int lineNumber = spawnpoint.getAttribute( IMarker.LINE_NUMBER, 0) + 1; final IDbgpSpawnpoint p = commands.setSpawnpoint(pathMapper .map(uri), lineNumber, true); // TODO save spawnpoint id - need SpawnpointManager? } catch (DbgpException e) { // TODO save spawnpoint error - need SpawnpointManager? TclActiveStateDebuggerPlugin.warn(e); } monitor.worked(1); } } catch (CoreException e) { TclActiveStateDebuggerPlugin.warn(e); } monitor.done(); } }