cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java
changeset 117 09f3d307f081
parent 37 c2bce6dd59e7
child 122 d94b9ba55bed
equal deleted inserted replaced
116:05ea843f7d56 117:09f3d307f081
    13  *     Ericsson   - Added Action support
    13  *     Ericsson   - Added Action support
    14  *******************************************************************************/
    14  *******************************************************************************/
    15 
    15 
    16 package org.eclipse.cdt.dsf.mi.service;
    16 package org.eclipse.cdt.dsf.mi.service;
    17 
    17 
    18 import java.util.ArrayList;
    18 import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator;
    19 import java.util.HashMap;
       
    20 import java.util.HashSet;
       
    21 import java.util.Hashtable;
       
    22 import java.util.List;
       
    23 import java.util.Map;
       
    24 import java.util.Set;
       
    25 import java.util.Vector;
       
    26 import java.util.concurrent.RejectedExecutionException;
       
    27 
       
    28 import org.eclipse.cdt.debug.core.CDebugCorePlugin;
       
    29 import org.eclipse.cdt.debug.core.breakpointactions.BreakpointActionManager;
       
    30 import org.eclipse.cdt.debug.core.model.ICAddressBreakpoint;
       
    31 import org.eclipse.cdt.debug.core.model.ICBreakpoint;
       
    32 import org.eclipse.cdt.debug.core.model.ICBreakpointExtension;
       
    33 import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
       
    34 import org.eclipse.cdt.debug.core.model.ICWatchpoint;
       
    35 import org.eclipse.cdt.debug.internal.core.breakpoints.BreakpointProblems;
       
    36 import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
       
    37 import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
       
    38 import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
       
    39 import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
       
    40 import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
       
    41 import org.eclipse.cdt.dsf.datamodel.DMContexts;
       
    42 import org.eclipse.cdt.dsf.datamodel.IDMContext;
       
    43 import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
       
    44 import org.eclipse.cdt.dsf.debug.service.IDsfBreakpointExtension;
       
    45 import org.eclipse.cdt.dsf.debug.service.IRunControl;
       
    46 import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
       
    47 import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
       
    48 import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
       
    49 import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
       
    50 import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
       
    51 import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
       
    52 import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
       
    53 import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
       
    54 import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
       
    55 import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.BreakpointAddedEvent;
       
    56 import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.BreakpointRemovedEvent;
       
    57 import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.BreakpointUpdatedEvent;
       
    58 import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext;
       
    59 import org.eclipse.cdt.dsf.mi.service.MIRunControl.SuspendedEvent;
       
    60 import org.eclipse.cdt.dsf.mi.service.breakpoint.actions.BreakpointActionAdapter;
       
    61 import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
       
    62 import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointScopeEvent;
       
    63 import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent;
       
    64 import org.eclipse.cdt.dsf.service.AbstractDsfService;
       
    65 import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
       
    66 import org.eclipse.cdt.dsf.service.DsfSession;
    19 import org.eclipse.cdt.dsf.service.DsfSession;
    67 import org.eclipse.core.resources.IMarker;
       
    68 import org.eclipse.core.resources.IMarkerDelta;
       
    69 import org.eclipse.core.resources.IResource;
       
    70 import org.eclipse.core.resources.IWorkspaceRunnable;
       
    71 import org.eclipse.core.resources.ResourcesPlugin;
       
    72 import org.eclipse.core.runtime.CoreException;
       
    73 import org.eclipse.core.runtime.IProgressMonitor;
       
    74 import org.eclipse.core.runtime.IStatus;
       
    75 import org.eclipse.core.runtime.Platform;
       
    76 import org.eclipse.core.runtime.Status;
       
    77 import org.eclipse.core.runtime.jobs.ISchedulingRule;
       
    78 import org.eclipse.core.runtime.jobs.Job;
       
    79 import org.eclipse.core.runtime.jobs.MultiRule;
       
    80 import org.eclipse.debug.core.DebugPlugin;
       
    81 import org.eclipse.debug.core.IBreakpointListener;
       
    82 import org.eclipse.debug.core.IBreakpointManager;
       
    83 import org.eclipse.debug.core.IBreakpointManagerListener;
       
    84 import org.eclipse.debug.core.model.IBreakpoint;
       
    85 import org.osgi.framework.BundleContext;
       
    86 
    20 
    87 /**
    21 /**
    88  * Breakpoint service interface.  The breakpoint service tracks CDT breakpoint
    22  * Breakpoint service interface.  The breakpoint service tracks CDT breakpoint
    89  * objects, and based on those, it manages breakpoints in the debugger back end.
    23  * objects, and based on those, it manages breakpoints in the debugger back end.
    90  * 
    24  * 
    91  * It relies on MIBreakpoints for the actual back-end interface.
    25  * It relies on MIBreakpoints for the actual back-end interface.
    92  */
    26  */
    93 public class MIBreakpointsManager extends AbstractDsfService implements IBreakpointManagerListener, IBreakpointListener
    27 public class MIBreakpointsManager extends BreakpointsMediator
    94 {
    28 {
    95     // Note: Find a way to import this (careful of circular dependencies)
       
    96     public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.cdt.dsf.gdb"; //$NON-NLS-1$
       
    97 
       
    98     // Extra breakpoint attributes
       
    99     private static final String ATTR_DEBUGGER_PATH = GdbPlugin.PLUGIN_ID + ".debuggerPath";   //$NON-NLS-1$
       
   100     private static final String ATTR_THREAD_FILTER = GdbPlugin.PLUGIN_ID + ".threadFilter";   //$NON-NLS-1$
       
   101     private static final String ATTR_THREAD_ID     = GdbPlugin.PLUGIN_ID + ".threadID";       //$NON-NLS-1$
       
   102 
       
   103     // Services
       
   104     ICommandControl    fConnection;
       
   105     IRunControl        fRunControl;
       
   106     ISourceLookup      fSourceLookup;
       
   107     IBreakpoints       fBreakpoints;
       
   108     IBreakpointManager fBreakpointManager;  // Platform breakpoint manager (not this!)
       
   109     BreakpointActionManager fBreakpointActionManager;
       
   110 
       
   111     ///////////////////////////////////////////////////////////////////////////
       
   112     // Breakpoints tracking
       
   113     ///////////////////////////////////////////////////////////////////////////
       
   114 
       
   115     private String fDebugModelId;
       
   116     
       
   117     // Holds the set of platform breakpoints with their corresponding back-end
       
   118     // breakpoint attributes, per context (i.e. each platform breakpoint is
       
   119     // replicated for each execution context).
       
   120     // - Context entry added/removed on start/stopTrackingBreakpoints()
       
   121     // - Augmented on breakpointAdded()
       
   122     // - Modified on breakpointChanged()
       
   123     // - Diminished on breakpointRemoved()
       
   124     private Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Map<String, Object>>> fPlatformBPs =
       
   125         new HashMap<IBreakpointsTargetDMContext, Map<ICBreakpoint, Map<String, Object>>>();
       
   126 
       
   127     // Holds the set of target breakpoints, per execution context, and their
       
   128     // mapping to the corresponding platform breakpoint. In a given execution
       
   129     // context there can only be one platform breakpoint per target breakpoint.
       
   130     // Acts as a mapping from target (low-level) BP to the corresponding platform
       
   131     // (high-level) BP.
       
   132     // Updated when:
       
   133     // - We start/stop tracking an execution context
       
   134     // - A platform breakpoint is added/removed
       
   135     // - A thread filter is applied/removed
       
   136     private Map<IBreakpointsTargetDMContext, Map<IBreakpointDMContext, ICBreakpoint>> fTargetBPs =
       
   137         new HashMap<IBreakpointsTargetDMContext, Map<IBreakpointDMContext, ICBreakpoint>>();
       
   138 
       
   139     // Holds the mapping from platform breakpoint to the corresponding target
       
   140     // breakpoint(s), per context. There can be multiple back-end BPs for a
       
   141     // single platform BP in the case of [1] multiple target contexts, and/or
       
   142     // [2] thread filtering.
       
   143     // Updated when:
       
   144     // - We start/stop tracking an execution context
       
   145     // - A platform breakpoint is added/removed
       
   146     // - A thread filter is applied/removed
       
   147     private Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Vector<IBreakpointDMContext>>> fBreakpointIDs =
       
   148         new HashMap<IBreakpointsTargetDMContext, Map<ICBreakpoint, Vector<IBreakpointDMContext>>>();
       
   149 
       
   150     // Holds the mapping from platform breakpoint to the corresponding target
       
   151     // breakpoint threads, per context.
       
   152     // Updated when:
       
   153     // - We start/stop tracking an execution context
       
   154     // - A platform breakpoint is added/removed
       
   155     // - A thread filter is applied/removed
       
   156     private Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Set<String>>> fBreakpointThreads =
       
   157         new HashMap<IBreakpointsTargetDMContext, Map<ICBreakpoint, Set<String>>>();
       
   158 
       
   159     // Due to the very asynchronous nature of DSF, a new breakpoint request can
       
   160     // pop up at any time before an ongoing one is completed. The following set
       
   161     // is used to store requests until the ongoing operation completes.
       
   162     private Set<IBreakpoint> fPendingRequests    = new HashSet<IBreakpoint>();
       
   163     private Set<IBreakpoint> fPendingBreakpoints = new HashSet<IBreakpoint>();
       
   164 
       
   165     private Map<ICBreakpoint, IMarker> fBreakpointMarkerProblems =
       
   166         new HashMap<ICBreakpoint, IMarker>();
       
   167 
       
   168     ///////////////////////////////////////////////////////////////////////////
       
   169     // String constants
       
   170     ///////////////////////////////////////////////////////////////////////////
       
   171 
       
   172     private static final String NULL_STRING = ""; //$NON-NLS-1$
       
   173 
       
   174     static final String CONTEXT_ALREADY_INITIALIZED  = "Context already initialized";  //$NON-NLS-1$
       
   175     static final String INVALID_CONTEXT_TYPE         = "Invalid context type";         //$NON-NLS-1$
       
   176     static final String INVALID_CONTEXT              = "Invalid context";              //$NON-NLS-1$
       
   177 
       
   178     static final String UNABLE_TO_READ_BREAKPOINT    = "Unable to read initial breakpoint attributes"; //$NON-NLS-1$
       
   179     static final String BREAKPOINT_NOT_INSTALLED     = "Breakpoints not installed for given context";  //$NON-NLS-1$
       
   180     static final String BREAKPOINT_ALREADY_INSTALLED = "Breakpoint already installed"; //$NON-NLS-1$
       
   181     static final String BREAKPOINT_ALREADY_REMOVED   = "Breakpoint already removed";   //$NON-NLS-1$
       
   182 
       
   183     static final String INVALID_BREAKPOINT           = "Invalid breakpoint";                    //$NON-NLS-1$
       
   184     static final String UNKNOWN_BREAKPOINT           = "Unknown breakpoint";                    //$NON-NLS-1$
       
   185     static final String INVALID_PARAMETER            = "Invalid breakpoint parameter(s)";       //$NON-NLS-1$
       
   186 
       
   187     static final String NO_DEBUGGER_PATH             = "No debugger path for breakpoint";       //$NON-NLS-1$
       
   188     static final String NO_MARKER_FOR_BREAKPOINT     = "No marker associated with breakpoint";  //$NON-NLS-1$
       
   189 
       
   190     ///////////////////////////////////////////////////////////////////////////
       
   191     // AbstractDsfService
       
   192     ///////////////////////////////////////////////////////////////////////////
       
   193 
       
   194     /**
    29     /**
   195      * The service constructor.
    30      * The service constructor.
   196      * Performs basic instantiation (method initialize() performs the real
    31      * Performs basic instantiation (method initialize() performs the real
   197      * service initialization asynchronously).
    32      * service initialization asynchronously).
   198      * 
    33      * 
   199      * @param session       the debugging session
    34      * @param session       the debugging session
   200      * @param debugModelId  the debugging model
    35      * @param debugModelId  the debugging model
   201      */
    36      */
   202     public MIBreakpointsManager(DsfSession session, String debugModelId) {
    37     public MIBreakpointsManager(DsfSession session, String debugModelId) {
   203         super(session);
    38         super(session, new MIBreakpointAttributeTranslator(session, debugModelId));
   204         fDebugModelId = debugModelId;
       
   205     }
    39     }
   206 
       
   207     //-------------------------------------------------------------------------
       
   208     // initialize
       
   209     //-------------------------------------------------------------------------
       
   210     // - Collect references for the services we interact with
       
   211     // - Register to interesting events
       
   212     // - Obtain the list of platform breakpoints
       
   213     // - Register the service for interested parties
       
   214     //-------------------------------------------------------------------------
       
   215 
       
   216     /* (non-Javadoc)
       
   217      * @see org.eclipse.cdt.dsf.service.AbstractDsfService#initialize(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
       
   218      */
       
   219     @Override
       
   220     public void initialize(final RequestMonitor rm) {
       
   221         super.initialize(
       
   222             new RequestMonitor(getExecutor(), rm) {
       
   223                 @Override
       
   224                 protected void handleSuccess() {
       
   225                     doInitialize(rm);
       
   226                 }});
       
   227     }
       
   228 
       
   229     /**
       
   230      * @param rm
       
   231      */
       
   232     private void doInitialize(RequestMonitor rm) {
       
   233         
       
   234         // Get the required services references from central repository
       
   235         fConnection     = getServicesTracker().getService(ICommandControl.class);
       
   236         fRunControl     = getServicesTracker().getService(IRunControl.class);
       
   237         fSourceLookup   = getServicesTracker().getService(ISourceLookup.class);
       
   238         fBreakpoints    = getServicesTracker().getService(IBreakpoints.class);
       
   239         fBreakpointManager = DebugPlugin.getDefault().getBreakpointManager();
       
   240         fBreakpointActionManager = CDebugCorePlugin.getDefault().getBreakpointActionManager();
       
   241 
       
   242         // Register to the useful events
       
   243         getSession().addServiceEventListener(this, null);
       
   244         fBreakpointManager.addBreakpointListener(this);
       
   245         fBreakpointManager.addBreakpointManagerListener(this);
       
   246 
       
   247         // And register this service
       
   248         register(new String[] { MIBreakpointsManager.class.getName() },
       
   249                  new Hashtable<String, String>());
       
   250         rm.done();
       
   251     }
       
   252 
       
   253     //-------------------------------------------------------------------------
       
   254     // shutdown
       
   255     //-------------------------------------------------------------------------
       
   256     // - Un-register the service
       
   257     // - Stop listening to events
       
   258     // - Remove the breakpoints installed by this service
       
   259     //
       
   260     //  Since we are shutting down, there is no overwhelming need
       
   261     //  to keep the maps coherent...
       
   262     //-------------------------------------------------------------------------
       
   263     
       
   264     /* (non-Javadoc)
       
   265      * @see org.eclipse.cdt.dsf.service.AbstractDsfService#shutdown(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
       
   266      */
       
   267     @Override
       
   268     public void shutdown(final RequestMonitor rm) {
       
   269 
       
   270         // Stop accepting requests and events
       
   271         unregister();
       
   272         getSession().removeServiceEventListener(this);
       
   273         fBreakpointManager.removeBreakpointListener(this);
       
   274         fBreakpointManager.removeBreakpointManagerListener(this);
       
   275 
       
   276         // Cleanup the breakpoints that are still installed by the service.
       
   277         // Use a counting monitor which will call mom to complete the shutdown
       
   278         // after the breakpoints are un-installed (successfully or not).
       
   279         CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) {
       
   280             @Override
       
   281             protected void handleCompleted() {
       
   282                 MIBreakpointsManager.super.shutdown(rm);
       
   283             }
       
   284         };
       
   285 
       
   286         List<IBreakpointsTargetDMContext> targetBPKeys = new ArrayList<IBreakpointsTargetDMContext>(fTargetBPs.size());
       
   287         targetBPKeys.addAll(0, fTargetBPs.keySet());
       
   288         for (IBreakpointsTargetDMContext dmc : targetBPKeys) {
       
   289             stopTrackingBreakpoints(dmc, countingRm);
       
   290         }
       
   291         countingRm.setDoneCount(targetBPKeys.size());
       
   292     }
       
   293 
       
   294     //-------------------------------------------------------------------------
       
   295     // getBundleContext
       
   296     //-------------------------------------------------------------------------
       
   297 
       
   298     /* (non-Javadoc)
       
   299      * @see org.eclipse.cdt.dsf.service.AbstractDsfService#getBundleContext()
       
   300      */
       
   301     @Override
       
   302     protected BundleContext getBundleContext() {
       
   303         return GdbPlugin.getBundleContext();
       
   304     }
       
   305 
       
   306     ///////////////////////////////////////////////////////////////////////////
       
   307     // IBreakpointsManager
       
   308     ///////////////////////////////////////////////////////////////////////////
       
   309 
       
   310     //-------------------------------------------------------------------------
       
   311     // startTrackingBreakpoints
       
   312     //-------------------------------------------------------------------------
       
   313     // - Augment the maps with the new execution context
       
   314     // - Install the platform breakpoints on the selected target
       
   315     //-------------------------------------------------------------------------
       
   316 
       
   317     /**
       
   318      * Install and begin tracking breakpoints for given context.  The service
       
   319      * will keep installing new breakpoints that appear in the IDE for this
       
   320      * context until {@link #uninstallBreakpoints(IDMContext)} is called for that
       
   321      * context.
       
   322      * @param dmc Context to start tracking breakpoints for.
       
   323      * @param rm Completion callback.
       
   324      */
       
   325     public void startTrackingBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {
       
   326 
       
   327         // Validate the execution context
       
   328         if (dmc == null) {
       
   329             rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_CONTEXT, null));
       
   330             rm.done();
       
   331             return;
       
   332         }
       
   333 
       
   334         // Make sure a mapping for this execution context does not already exist
       
   335         Map<ICBreakpoint,Map<String, Object>> platformBPs = fPlatformBPs.get(dmc);
       
   336         Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
       
   337         Map<IBreakpointDMContext, ICBreakpoint> targetIDs = fTargetBPs.get(dmc);
       
   338         Map<ICBreakpoint, Set<String>> threadIDs = fBreakpointThreads.get(dmc);
       
   339         if ((platformBPs != null) || (breakpointIDs != null) || (targetIDs != null) || (threadIDs != null)) {
       
   340             rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, CONTEXT_ALREADY_INITIALIZED, null));
       
   341             rm.done();
       
   342             return;
       
   343         }
       
   344 
       
   345         // Create entries in the breakpoint tables for the new context. These entries should only
       
   346         // be removed when this service stops tracking breakpoints for the given context.
       
   347         fPlatformBPs.put(dmc, new HashMap<ICBreakpoint, Map<String, Object>>());
       
   348         fBreakpointIDs.put(dmc, new HashMap<ICBreakpoint, Vector<IBreakpointDMContext>>());
       
   349         fTargetBPs.put(dmc, new HashMap<IBreakpointDMContext, ICBreakpoint>());
       
   350         fBreakpointThreads.put(dmc, new HashMap<ICBreakpoint, Set<String>>());
       
   351 
       
   352         // Install the platform breakpoints (stored in fPlatformBPs) on the target.
       
   353         new Job("DSF BreakpointsManager: Install initial breakpoints on target") { //$NON-NLS-1$
       
   354             @Override
       
   355             protected IStatus run(IProgressMonitor monitor) {
       
   356                 // Submit the runnable to plant the breakpoints on dispatch thread.
       
   357                 getExecutor().submit(new Runnable() {
       
   358                     public void run() {
       
   359                         installInitialBreakpoints(dmc, rm);
       
   360                     }
       
   361                 });
       
   362 
       
   363                 return Status.OK_STATUS;
       
   364             }
       
   365         }.schedule();
       
   366     }
       
   367 
       
   368     /**
       
   369      * Installs the breakpoints that existed prior to the activation of this
       
   370      * execution context.
       
   371      * 
       
   372      * @param dmc
       
   373      * @param initialPlatformBPs
       
   374      * @param rm
       
   375      */
       
   376     private void installInitialBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm)
       
   377     {
       
   378         // Retrieve the set of platform breakpoints for this context
       
   379         final Map<ICBreakpoint,Map<String, Object>> platformBPs = fPlatformBPs.get(dmc);
       
   380         if (platformBPs == null) {
       
   381             rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, INVALID_CONTEXT, null));
       
   382             rm.done();
       
   383             return;
       
   384         }
       
   385 
       
   386         // Read current breakpoints from platform and copy their augmented
       
   387         // attributes into the local reference map
       
   388         try {
       
   389             IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(fDebugModelId);
       
   390             for (IBreakpoint breakpoint : breakpoints) {
       
   391                 if (supportsBreakpoint(breakpoint)) {
       
   392                     @SuppressWarnings("unchecked")
       
   393                     Map<String, Object> attributes = breakpoint.getMarker().getAttributes();
       
   394                     attributes.put(ATTR_DEBUGGER_PATH, NULL_STRING);
       
   395                     attributes.put(ATTR_THREAD_FILTER, extractThreads(dmc, (ICBreakpoint) breakpoint));
       
   396                     attributes.put(ATTR_THREAD_ID, NULL_STRING);
       
   397                     platformBPs.put((ICBreakpoint) breakpoint, attributes);
       
   398                 }
       
   399             }
       
   400         } catch (CoreException e) {
       
   401             IStatus status = new Status(
       
   402                 IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, UNABLE_TO_READ_BREAKPOINT, e);
       
   403             rm.setStatus(status);
       
   404             rm.done();
       
   405         }
       
   406 
       
   407         // Install the individual breakpoints on the dispatcher thread
       
   408         // Requires a counting monitor to know when we are done
       
   409         final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm);
       
   410         countingRm.setDoneCount(platformBPs.size());
       
   411 
       
   412         for (final ICBreakpoint breakpoint : platformBPs.keySet()) {
       
   413             final Map<String, Object> attributes = platformBPs.get(breakpoint);
       
   414             // Upon determining the debuggerPath, the breakpoint is installed
       
   415             determineDebuggerPath(dmc, attributes, new RequestMonitor(getExecutor(), countingRm) {
       
   416                 @Override
       
   417                 protected void handleSuccess() {
       
   418                 	// Install only if the breakpoint is enabled at startup (Bug261082)
       
   419                 	boolean bpEnabled = attributes.get(ICBreakpoint.ENABLED).equals(true) && fBreakpointManager.isEnabled();
       
   420                 	if (bpEnabled)
       
   421                 		installBreakpoint(dmc, breakpoint, attributes, countingRm);
       
   422                 	else
       
   423                 		countingRm.done();
       
   424                 }
       
   425             });
       
   426         }
       
   427     }
       
   428 
       
   429     //-------------------------------------------------------------------------
       
   430     // stopTrackingBreakpoints
       
   431     //-------------------------------------------------------------------------
       
   432     // - Remove the target breakpoints for the given execution context
       
   433     // - Update the maps
       
   434     //-------------------------------------------------------------------------
       
   435 
       
   436     /**
       
   437      * Uninstall and stop tracking breakpoints for the given context.
       
   438      * @param dmc Context to start tracking breakpoints for.
       
   439      * @param rm Completion callback.
       
   440      */
       
   441     public void stopTrackingBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {
       
   442 
       
   443         // Validate the context
       
   444         if (dmc == null) {
       
   445             rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, INVALID_CONTEXT, null));
       
   446             rm.done();
       
   447             return;
       
   448         }
       
   449 
       
   450         // Retrieve the set of platform breakpoints for this context
       
   451         final Map<ICBreakpoint,Map<String, Object>> platformBPs = fPlatformBPs.get(dmc);
       
   452         if (platformBPs == null) {
       
   453             rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, INVALID_CONTEXT, null));
       
   454             rm.done();
       
   455             return;
       
   456         }
       
   457 
       
   458         // Un-install the individual breakpoints on the dispatcher thread
       
   459         // (requires a counting monitor to know when we are done).
       
   460         // On completion (success or failure), update the maps.
       
   461         final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) {
       
   462             @Override
       
   463             protected void handleCompleted() {
       
   464                 fPlatformBPs.remove(dmc);
       
   465                 fBreakpointIDs.remove(dmc);
       
   466                 fTargetBPs.remove(dmc);
       
   467                 fBreakpointThreads.remove(dmc);
       
   468                 rm.done();
       
   469             }
       
   470         };
       
   471         countingRm.setDoneCount(platformBPs.size());
       
   472 
       
   473         for (final ICBreakpoint breakpoint : platformBPs.keySet()) {
       
   474             uninstallBreakpoint(dmc, breakpoint,
       
   475                 new RequestMonitor(getExecutor(), countingRm) {
       
   476                     @Override
       
   477                     protected void handleCompleted() {
       
   478                         countingRm.done();
       
   479                     }
       
   480                 });
       
   481         }
       
   482     }
       
   483 
       
   484     ///////////////////////////////////////////////////////////////////////////
       
   485     // Back-end interface functions
       
   486     ///////////////////////////////////////////////////////////////////////////
       
   487 
       
   488     //-------------------------------------------------------------------------
       
   489     // installBreakpoint
       
   490     //-------------------------------------------------------------------------
       
   491 
       
   492     /**
       
   493      * Install a platform breakpoint on the back-end. For a given context, a
       
   494      * platform breakpoint can resolve into multiple back-end breakpoints when
       
   495      * threads are taken into account.
       
   496      * 
       
   497      * @param dmc
       
   498      * @param breakpoint
       
   499      * @param attributes
       
   500      * @param rm
       
   501      */
       
   502     private void installBreakpoint(IBreakpointsTargetDMContext dmc, final ICBreakpoint breakpoint,
       
   503         final Map<String, Object> attributes, final RequestMonitor rm)
       
   504     {
       
   505         // Retrieve the breakpoint maps
       
   506         final Map<ICBreakpoint,Map<String,Object>> platformBPs = fPlatformBPs.get(dmc);
       
   507         assert platformBPs != null;
       
   508 
       
   509         final Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
       
   510         assert breakpointIDs != null;
       
   511 
       
   512         final Map<IBreakpointDMContext, ICBreakpoint> targetBPs = fTargetBPs.get(dmc);
       
   513         assert targetBPs != null;
       
   514 
       
   515         final Map<ICBreakpoint, Set<String>> threadsIDs = fBreakpointThreads.get(dmc);
       
   516         assert threadsIDs != null;
       
   517 
       
   518         // Minimal validation
       
   519         if (breakpointIDs.containsKey(breakpoint) || targetBPs.containsValue(breakpoint)) {
       
   520             rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, BREAKPOINT_ALREADY_INSTALLED, null));
       
   521             rm.done();
       
   522             return;
       
   523         }
       
   524 
       
   525         // Ensure the breakpoint has a valid debugger source path
       
   526         if (breakpoint instanceof ICLineBreakpoint && !(breakpoint instanceof ICAddressBreakpoint)) {
       
   527             String debuggerPath = (String) attributes.get(ATTR_DEBUGGER_PATH);
       
   528             if (debuggerPath == null || debuggerPath == NULL_STRING) {
       
   529                 rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, NO_DEBUGGER_PATH, null));
       
   530                 rm.done();
       
   531                 return;
       
   532             }
       
   533         }
       
   534 
       
   535         // A back-end breakpoint needs to be installed for each specified thread
       
   536         // Note: This is a bit academic since [1] thread info is not kept by the
       
   537         // BreakpointManager (so it can not possibly be restored when a target is
       
   538         // started), and [2] the standard GUI doesn't allow to specify thread at
       
   539         // breakpoint creation. However, it is conceivable that an enhanced Editor
       
   540         // would permit it.
       
   541         final Set<String> threads = getThreads(attributes);
       
   542 
       
   543         // Update the breakpoint state when all back-end breakpoints have been installed
       
   544         final CountingRequestMonitor installRM = new CountingRequestMonitor(getExecutor(), rm) {
       
   545             @Override
       
   546             protected void handleCompleted() {
       
   547                 // Store the platform breakpoint
       
   548                 platformBPs.put(breakpoint, attributes);
       
   549                 rm.done();
       
   550             }
       
   551         };
       
   552         installRM.setDoneCount(threads.size());
       
   553 
       
   554         // Install the back-end breakpoint(s)
       
   555         for (final String thread : threads) {
       
   556             DataRequestMonitor<IBreakpointDMContext> drm =
       
   557                 new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), installRM) {
       
   558                     @Override
       
   559                     protected void handleSuccess() {
       
   560                         // Add the new back-end breakpoint to the map
       
   561                         Vector<IBreakpointDMContext> list = breakpointIDs.get(breakpoint);
       
   562                         if (list == null)
       
   563                             list = new Vector<IBreakpointDMContext>();
       
   564                         IBreakpointDMContext targetBP = getData();
       
   565                         list.add(targetBP);
       
   566                         breakpointIDs.put(breakpoint, list);
       
   567 
       
   568                         // Add the reverse mapping
       
   569                         targetBPs.put(targetBP, breakpoint);
       
   570 
       
   571                         // And update the corresponding thread list
       
   572                         Set<String> thrds = threadsIDs.get(breakpoint);
       
   573                         if (thrds == null)
       
   574                             thrds = new HashSet<String>();
       
   575                         thrds.add(thread);
       
   576                         threadsIDs.put(breakpoint, thrds);
       
   577 
       
   578                         // Reset the thread (is it necessary?)
       
   579                         attributes.put(ATTR_THREAD_ID, NULL_STRING);
       
   580 
       
   581                         // Remove breakpoint problem marker (if any)
       
   582                         removeBreakpointProblemMarker(breakpoint);
       
   583 
       
   584                         // Finally, update the platform breakpoint
       
   585                         try {
       
   586 							breakpoint.incrementInstallCount();
       
   587 						} catch (CoreException e) {
       
   588 						}
       
   589                         installRM.done();
       
   590                     }
       
   591 
       
   592                     @Override
       
   593                     protected void handleError() {
       
   594                         addBreakpointProblemMarker(breakpoint, "Breakpoint attribute problem: installation failed", IMarker.SEVERITY_WARNING); //$NON-NLS-1$
       
   595                         installRM.done();
       
   596                     }
       
   597                 };
       
   598 
       
   599             // Convert the breakpoint attributes for the back-end
       
   600             attributes.put(ATTR_THREAD_ID, thread);
       
   601             Map<String,Object> targetAttributes = convertToTargetBreakpoint(breakpoint, attributes);
       
   602             fBreakpoints.insertBreakpoint(dmc, targetAttributes, drm);
       
   603         }
       
   604     }
       
   605 
       
   606     private void addBreakpointProblemMarker(final ICBreakpoint breakpoint, final String description, final int severity) {
       
   607 
       
   608         new Job("Add Breakpoint Problem Marker") { //$NON-NLS-1$
       
   609             @Override
       
   610             protected IStatus run(IProgressMonitor monitor) {
       
   611                 
       
   612                 if (breakpoint instanceof ICLineBreakpoint) {
       
   613                 	// If we have already have a problem marker on this breakpoint
       
   614                 	// we should remove it first.
       
   615                     IMarker marker = fBreakpointMarkerProblems.remove(breakpoint);
       
   616                     if (marker != null) {
       
   617                         try {
       
   618                             marker.delete();
       
   619                         } catch (CoreException e) {
       
   620                         }
       
   621                 	}
       
   622 
       
   623                     ICLineBreakpoint lineBreakpoint = (ICLineBreakpoint) breakpoint;
       
   624                     try {
       
   625                         // Locate the workspace resource via the breakpoint marker
       
   626                         IMarker breakpoint_marker = lineBreakpoint.getMarker();
       
   627                         IResource resource = breakpoint_marker.getResource();
       
   628 
       
   629                         // Add a problem marker to the resource
       
   630                         IMarker problem_marker = resource.createMarker(BreakpointProblems.BREAKPOINT_PROBLEM_MARKER_ID);
       
   631                         int line_number = lineBreakpoint.getLineNumber();
       
   632                         problem_marker.setAttribute(IMarker.LOCATION,    String.valueOf(line_number));
       
   633                         problem_marker.setAttribute(IMarker.MESSAGE,     description);
       
   634                         problem_marker.setAttribute(IMarker.SEVERITY,    severity);
       
   635                         problem_marker.setAttribute(IMarker.LINE_NUMBER, line_number);
       
   636 
       
   637                         // And save the baby
       
   638                         fBreakpointMarkerProblems.put(breakpoint, problem_marker);
       
   639                     } catch (CoreException e) {
       
   640                     }
       
   641                 }
       
   642                 return Status.OK_STATUS;
       
   643             }
       
   644         }.schedule();
       
   645     }
       
   646 
       
   647     private void removeBreakpointProblemMarker(final ICBreakpoint breakpoint) {
       
   648 
       
   649         new Job("Remove Breakpoint Problem Marker") { //$NON-NLS-1$
       
   650             @Override
       
   651             protected IStatus run(IProgressMonitor monitor) {
       
   652                 
       
   653                 IMarker marker = fBreakpointMarkerProblems.remove(breakpoint);
       
   654                 if (marker != null) {
       
   655                     try {
       
   656                         marker.delete();
       
   657                     } catch (CoreException e) {
       
   658                     }
       
   659                 }
       
   660 
       
   661                 return Status.OK_STATUS;
       
   662             }
       
   663         }.schedule();
       
   664     }
       
   665 
       
   666     //-------------------------------------------------------------------------
       
   667     // uninstallBreakpoint
       
   668     //-------------------------------------------------------------------------
       
   669 
       
   670     /**
       
   671      * Un-install an individual breakpoint on the back-end. For one platform
       
   672      * breakpoint in a given execution context, there could be multiple
       
   673      * corresponding back-end breakpoints (one per thread).
       
   674      * 
       
   675      * @param dmc
       
   676      * @param breakpoint
       
   677      * @param rm
       
   678      */
       
   679     private void uninstallBreakpoint(final IBreakpointsTargetDMContext dmc,
       
   680             final ICBreakpoint breakpoint, final RequestMonitor rm)
       
   681     {
       
   682         // Retrieve the breakpoint maps
       
   683         final Map<ICBreakpoint,Map<String,Object>> platformBPs = fPlatformBPs.get(dmc);
       
   684         assert platformBPs != null;
       
   685 
       
   686         final Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
       
   687         assert breakpointIDs != null;
       
   688 
       
   689         final Map<IBreakpointDMContext, ICBreakpoint> targetBPs = fTargetBPs.get(dmc);
       
   690         assert targetBPs != null;
       
   691 
       
   692         final Map<ICBreakpoint, Set<String>> threadsIDs = fBreakpointThreads.get(dmc);
       
   693         assert threadsIDs != null;
       
   694 
       
   695         // Remove breakpoint problem marker (if any)
       
   696         removeBreakpointProblemMarker(breakpoint);
       
   697 
       
   698         // Minimal validation
       
   699         if (!platformBPs.containsKey(breakpoint) || !breakpointIDs.containsKey(breakpoint) || !targetBPs.containsValue(breakpoint)) {
       
   700             rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, BREAKPOINT_ALREADY_REMOVED, null));
       
   701             rm.done();
       
   702             return;
       
   703         }
       
   704 
       
   705         // Remove completion monitor
       
   706         // Upon completion, update the mappings
       
   707         CountingRequestMonitor removeRM = new CountingRequestMonitor(getExecutor(), rm) {
       
   708             @Override
       
   709             protected void handleSuccess() {
       
   710                 // Update the mappings
       
   711                 platformBPs.remove(breakpoint);
       
   712                 threadsIDs.remove(breakpoint);
       
   713 
       
   714                 Vector<IBreakpointDMContext> contexts = breakpointIDs.get(breakpoint);
       
   715                 if (contexts != null) {
       
   716                     for (IBreakpointDMContext context : contexts)
       
   717                         targetBPs.remove(context);
       
   718                 }
       
   719 
       
   720                 breakpointIDs.get(breakpoint).clear();
       
   721                 breakpointIDs.remove(breakpoint);
       
   722 
       
   723                 fPendingRequests.remove(breakpoint);
       
   724 
       
   725 				rm.done();
       
   726             }
       
   727         };
       
   728 
       
   729         // Remove the back-end breakpoints
       
   730         Vector<IBreakpointDMContext> list = breakpointIDs.get(breakpoint);
       
   731         int count = 0;
       
   732         if (list != null) {
       
   733             for (IBreakpointDMContext bp : list) {
       
   734                 fBreakpoints.removeBreakpoint(bp, removeRM);
       
   735                 try {
       
   736 					breakpoint.decrementInstallCount();
       
   737 				} catch (CoreException e) {
       
   738 				}
       
   739             }
       
   740             count = list.size();
       
   741         }
       
   742         removeRM.setDoneCount(count);
       
   743     }
       
   744 
       
   745     //-------------------------------------------------------------------------
       
   746     // modifyBreakpoint
       
   747     //-------------------------------------------------------------------------
       
   748 
       
   749     /**
       
   750      * Modify a platform breakpoint which can translate to quite a few updates
       
   751      * on the target...
       
   752      * 
       
   753      * @param dmc
       
   754      * @param breakpoint
       
   755      * @param attributes
       
   756      * @param oldValues
       
   757      * @param rm
       
   758      */
       
   759     private void modifyBreakpoint(final IBreakpointsTargetDMContext dmc, final ICBreakpoint breakpoint,
       
   760             final Map<String,Object> attributes, final IMarkerDelta oldValues, final RequestMonitor rm)
       
   761     {
       
   762         // Retrieve the breakpoint maps
       
   763         final Map<ICBreakpoint,Map<String,Object>> platformBPs = fPlatformBPs.get(dmc);
       
   764         assert platformBPs != null;
       
   765 
       
   766         final Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
       
   767         assert breakpointIDs != null;
       
   768 
       
   769         final Map<IBreakpointDMContext, ICBreakpoint> targetBPs = fTargetBPs.get(dmc);
       
   770         assert targetBPs != null;
       
   771 
       
   772         final Map<ICBreakpoint, Set<String>> threadsIDs = fBreakpointThreads.get(dmc);
       
   773         assert threadsIDs != null;
       
   774 
       
   775         // Minimal validation
       
   776         if (!platformBPs.containsKey(breakpoint)) {
       
   777             rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, UNKNOWN_BREAKPOINT, null));
       
   778             rm.done();
       
   779             return;
       
   780         }
       
   781 
       
   782         // Check if the breakpoint is installed: it might not have been if it wasn't enabled at startup (Bug261082)
       
   783         // Or the installation might have failed; in this case, we still try to install it again because
       
   784         // some attribute might have changed which will make the install succeed.
       
   785         if (!breakpointIDs.containsKey(breakpoint) && !targetBPs.containsValue(breakpoint)) {
       
   786         	// Install only if the breakpoint is enabled
       
   787         	boolean bpEnabled = attributes.get(ICBreakpoint.ENABLED).equals(true) && fBreakpointManager.isEnabled();
       
   788         	if (bpEnabled) {
       
   789                 attributes.put(ATTR_DEBUGGER_PATH, NULL_STRING);
       
   790                 attributes.put(ATTR_THREAD_FILTER, extractThreads(dmc, breakpoint));
       
   791                 attributes.put(ATTR_THREAD_ID, NULL_STRING);
       
   792                 determineDebuggerPath(dmc, attributes, new RequestMonitor(getExecutor(), rm) {
       
   793                     @Override
       
   794                     protected void handleSuccess() {
       
   795                       	installBreakpoint(dmc, breakpoint, attributes, rm);
       
   796                     }
       
   797                 });
       
   798         	}
       
   799         	else {
       
   800                 rm.done();
       
   801         	}
       
   802        		return;
       
   803         }
       
   804 
       
   805         // Get the original breakpoint attributes
       
   806         final Map<String,Object> original_attributes = platformBPs.get(breakpoint);
       
   807         if (original_attributes == null) {
       
   808             rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, INVALID_BREAKPOINT, null));
       
   809             rm.done();
       
   810             return;
       
   811         }
       
   812 
       
   813         // Determine the attributes delta
       
   814         final Map<String,Object> oldAttributes = new HashMap<String,Object>(original_attributes);
       
   815         oldAttributes.put(ATTR_THREAD_FILTER, threadsIDs.get(breakpoint));
       
   816 
       
   817         final Set<String> newThreads = extractThreads(dmc, breakpoint);
       
   818         Map<String,Object> newAttributes = new HashMap<String,Object>(attributes);
       
   819         newAttributes.put(ATTR_THREAD_FILTER, newThreads);
       
   820 
       
   821         final Map<String,Object> attributesDelta = determineAttributesDelta(oldAttributes, newAttributes);
       
   822 
       
   823         // Get the list of back-end breakpoints
       
   824         final Vector<IBreakpointDMContext> oldTargetBPs = new Vector<IBreakpointDMContext>(breakpointIDs.get(breakpoint));
       
   825         if (oldTargetBPs == null) {
       
   826             rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, INVALID_BREAKPOINT, null));
       
   827             rm.done();
       
   828             return;
       
   829         }
       
   830 
       
   831         // We're all set for the breakpoint update.
       
   832         //
       
   833         // The path for a simple update is straightforward:
       
   834         // - For each back-end BP corresponding to a platform BP
       
   835         //   - Send an update command to the back-end
       
   836         //   - If the operation succeeded, update the data structures
       
   837         //   - If the operation failed, try to roll-back
       
   838         //
       
   839         // In cases where the the back-end breakpoint cannot be
       
   840         // simply updated (e.g. thread filter modification), the old
       
   841         // breakpoint has to be removed and new one(s) inserted.
       
   842         //
       
   843         // The path for such an update is:
       
   844         // - Install the updated breakpoint
       
   845         // - In the operation succeeded
       
   846         //   - Remove the old breakpoint(s)
       
   847         //   - Perform any pending update
       
   848 
       
   849         // Update completion monitor
       
   850         final CountingRequestMonitor updateRM = new CountingRequestMonitor(getExecutor(), rm) {
       
   851             @Override
       
   852             protected void handleSuccess() {
       
   853                 // Success: simply store the new attributes
       
   854                 platformBPs.put(breakpoint, attributes);
       
   855                 rm.done();
       
   856             }
       
   857 
       
   858             @Override
       
   859             protected void handleError() {
       
   860                 // Reset the breakpoint attributes. This will trigger a
       
   861                 // breakpoint change event and the correct delta will be
       
   862                 // computed, resulting in a correctly restored breakpoint
       
   863                 // at the back-end.
       
   864                 rollbackAttributes(breakpoint, oldValues);
       
   865                 platformBPs.put(breakpoint, attributes);
       
   866 
       
   867                 rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_PARAMETER, null));
       
   868                 rm.done();
       
   869             }
       
   870         };
       
   871 
       
   872         // Everything OK: remove the old back-end breakpoints
       
   873         final Vector<IBreakpointDMContext> newTargetBPs = new Vector<IBreakpointDMContext>();
       
   874         final CountingRequestMonitor removeRM = new CountingRequestMonitor(getExecutor(), rm) {
       
   875             @Override
       
   876             protected void handleSuccess() {
       
   877                 // All right! Save the new list and perform the final update
       
   878                 Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
       
   879                 if (breakpointIDs == null) {
       
   880                     rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_BREAKPOINT, null));
       
   881                     rm.done();
       
   882                     return;
       
   883                 }
       
   884                 breakpointIDs.put(breakpoint, newTargetBPs);
       
   885                 for (IBreakpointDMContext ref : newTargetBPs) {
       
   886                     fBreakpoints.updateBreakpoint(ref, attributesDelta, updateRM);
       
   887                 }
       
   888                 updateRM.setDoneCount(newTargetBPs.size());
       
   889             }};
       
   890 
       
   891         // New back-end breakpoints insertion monitor
       
   892         // Holds the list of new back-end breakpoint contexts of the platform breakpoint
       
   893         final DataRequestMonitor<Vector<IBreakpointDMContext>> insertRM =
       
   894             new DataRequestMonitor<Vector<IBreakpointDMContext>>(getExecutor(), null) {
       
   895 
       
   896                 @Override
       
   897                 // In theory, we could have had a partial success and the original threads
       
   898                 // list would be invalid. We think it is highly unlikely so we assume that
       
   899                 // either everything went fine or else everything failed.
       
   900                 protected void handleSuccess() {
       
   901                     // Get the list of new back-end breakpoints contexts
       
   902                     newTargetBPs.addAll(getData());
       
   903                     threadsIDs.put(breakpoint, newThreads);
       
   904                     for (IBreakpointDMContext ref : oldTargetBPs) {
       
   905                         fBreakpoints.removeBreakpoint(ref, removeRM);
       
   906                         try {
       
   907 							breakpoint.decrementInstallCount();  // A tad early but it should work...
       
   908 						} catch (CoreException e) {
       
   909 						}
       
   910                     }
       
   911                     removeRM.setDoneCount(oldTargetBPs.size());
       
   912                 }
       
   913                 
       
   914                 @Override
       
   915                 protected void handleError() {
       
   916                     // Keep the old threads list and reset the attributes
       
   917                     // (bad attributes are the likely cause of failure)
       
   918                     updateRM.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_PARAMETER, null));
       
   919                     updateRM.setDoneCount(0);
       
   920                 }
       
   921         };
       
   922 
       
   923         // If the changes in the breakpoint attributes justify it, install a
       
   924         // new set of back-end breakpoint(s) and then update them
       
   925         if (needsResinstallation(attributesDelta)) {
       
   926             reinstallBreakpoint(dmc, breakpoint, attributes, newThreads, insertRM);
       
   927         }
       
   928         else {
       
   929             // Update the back-end breakpoint(s) state
       
   930             for (IBreakpointDMContext ref : oldTargetBPs) {
       
   931                 fBreakpoints.updateBreakpoint(ref, attributesDelta, updateRM);
       
   932             }
       
   933             updateRM.setDoneCount(oldTargetBPs.size());
       
   934         }
       
   935     }
       
   936 
       
   937     /**
       
   938      * Re-install the back-end breakpoints
       
   939      * 
       
   940      * @param context       the target context
       
   941      * @param breakpoint    the platform breakpoint
       
   942      * @param attributes    breakpoint augmented attributes
       
   943      * @param threads       list of threads where breakpoint is to be installed
       
   944      * @param drm           will contain the list of successfully installed back-end breakpoints
       
   945      */
       
   946     private void reinstallBreakpoint(final IBreakpointsTargetDMContext context, final ICBreakpoint breakpoint,
       
   947             final Map<String,Object> attributes, Set<String> threads, final DataRequestMonitor<Vector<IBreakpointDMContext>> drm)
       
   948     {
       
   949         // Our new list of back-end breakpoints. Built as we go.
       
   950         final Vector<IBreakpointDMContext> breakpointList = new Vector<IBreakpointDMContext>();
       
   951 
       
   952         // Counting monitor for the new back-end breakpoints to install
       
   953         // Once we're done, return the new list of back-end breakpoints contexts
       
   954         final CountingRequestMonitor installRM = new CountingRequestMonitor(getExecutor(), drm) {
       
   955             @Override
       
   956             protected void handleSuccess() {
       
   957                 // Report whatever we have managed to install
       
   958                 // It is very likely installation either succeeded or failed for all
       
   959                 drm.setData(breakpointList);
       
   960                 drm.done();
       
   961             }
       
   962         };
       
   963         installRM.setDoneCount(threads.size());
       
   964 
       
   965         // And install the new back-end breakpoints
       
   966         for (String thread : threads) {
       
   967             // Convert the breakpoint attributes for the back-end
       
   968             // Refresh the set of attributes at each iteration just in case...
       
   969             Map<String,Object> attrs = convertToTargetBreakpoint(breakpoint, attributes);
       
   970             if (!fBreakpointManager.isEnabled()) {
       
   971                 attrs.put(MIBreakpoints.IS_ENABLED, false);
       
   972             }
       
   973             // Add the secret ingredient..
       
   974             attrs.put(MIBreakpointDMData.THREAD_ID, thread);
       
   975 
       
   976             // Then install the spiked breakpoint
       
   977             fBreakpoints.insertBreakpoint(context, attrs,
       
   978                 new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), installRM) {
       
   979                     @Override
       
   980                     protected void handleSuccess() {
       
   981                         // Add the new back-end breakpoint context to the list
       
   982                         breakpointList.add(getData());
       
   983                         try {
       
   984 							breakpoint.incrementInstallCount();
       
   985 						} catch (CoreException e) {
       
   986 						}
       
   987                         installRM.done();
       
   988                     }
       
   989 
       
   990                     @Override
       
   991                     protected void handleError() {
       
   992                         // Add the new back-end breakpoint context to the list
       
   993                         installRM.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_PARAMETER, null));
       
   994                         installRM.done();
       
   995                     }
       
   996             });
       
   997         }
       
   998     }
       
   999 
       
  1000     ///////////////////////////////////////////////////////////////////////////
       
  1001     // IBreakpointManagerListener implementation
       
  1002     ///////////////////////////////////////////////////////////////////////////
       
  1003 
       
  1004     /* (non-Javadoc)
       
  1005      * @see org.eclipse.debug.core.IBreakpointManagerListener#breakpointManagerEnablementChanged(boolean)
       
  1006      */
       
  1007     public void breakpointManagerEnablementChanged(boolean enabled) {
       
  1008 
       
  1009         // Only modify enabled breakpoints
       
  1010         for (IBreakpointsTargetDMContext context : fBreakpointIDs.keySet()) {
       
  1011             for (ICBreakpoint breakpoint : fBreakpointIDs.get(context).keySet()) {
       
  1012                 try {
       
  1013                     if (breakpoint.isEnabled()) {
       
  1014                         for (IBreakpointDMContext ref : fBreakpointIDs.get(context).get(breakpoint)) {
       
  1015                             Map<String,Object> delta = new HashMap<String,Object>();
       
  1016                             delta.put(MIBreakpoints.IS_ENABLED, enabled);
       
  1017                             fBreakpoints.updateBreakpoint(ref, delta, new RequestMonitor(getExecutor(), null));
       
  1018                         }
       
  1019                     }
       
  1020                 } catch (CoreException e) {
       
  1021                 }
       
  1022             }
       
  1023         }
       
  1024     }
       
  1025 
       
  1026     ///////////////////////////////////////////////////////////////////////////
       
  1027     // IBreakpointListener implementation
       
  1028     ///////////////////////////////////////////////////////////////////////////
       
  1029 
       
  1030     /* (non-Javadoc)
       
  1031      * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint)
       
  1032      */
       
  1033     @ThreadSafe
       
  1034     public void breakpointAdded(final IBreakpoint breakpoint) {
       
  1035 
       
  1036         if (supportsBreakpoint(breakpoint)) {
       
  1037             try {
       
  1038                 // Retrieve the breakpoint attributes
       
  1039                 @SuppressWarnings("unchecked")
       
  1040                 final Map<String, Object> attrs = breakpoint.getMarker().getAttributes();
       
  1041 
       
  1042                 getExecutor().execute(new DsfRunnable() {
       
  1043                     public void run() {
       
  1044                         final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
       
  1045                             @Override
       
  1046                             protected void handleError() {
       
  1047                                 if (getStatus().getSeverity() == IStatus.ERROR) {
       
  1048                                     GdbPlugin.getDefault().getLog().log(getStatus());
       
  1049                                 }
       
  1050                             }
       
  1051                         };
       
  1052                         countingRm.setDoneCount(fPlatformBPs.size());
       
  1053 
       
  1054                         // Install the breakpoint in all the execution contexts
       
  1055                         for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
       
  1056                             determineDebuggerPath(dmc, attrs,
       
  1057                                     new RequestMonitor(getExecutor(), countingRm) {
       
  1058                                     @Override
       
  1059                                     protected void handleSuccess() {
       
  1060                                         installBreakpoint(dmc, (ICBreakpoint) breakpoint,
       
  1061                                             attrs, countingRm);
       
  1062                                     }
       
  1063                                 });
       
  1064                         }
       
  1065                     }
       
  1066                 });
       
  1067             } catch (CoreException e) {
       
  1068             } catch (RejectedExecutionException e) {
       
  1069             }
       
  1070         }
       
  1071     }
       
  1072 
       
  1073     /**
       
  1074      * @param bp
       
  1075      * @return
       
  1076      * @throws CoreException
       
  1077      */
       
  1078     private IDsfBreakpointExtension getFilterExtension(ICBreakpoint bp) throws CoreException {
       
  1079         return (IDsfBreakpointExtension) bp.getExtension(GDB_DEBUG_MODEL_ID, ICBreakpointExtension.class);
       
  1080     }
       
  1081 
       
  1082     /* (non-Javadoc)
       
  1083      * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
       
  1084      */
       
  1085     public void breakpointChanged(final IBreakpoint breakpoint, final IMarkerDelta delta) {
       
  1086 
       
  1087         if (supportsBreakpoint(breakpoint)) {
       
  1088 
       
  1089             try {
       
  1090                 // Retrieve the breakpoint attributes
       
  1091                 @SuppressWarnings("unchecked")
       
  1092                 final Map<String, Object> attrs = breakpoint.getMarker().getAttributes();
       
  1093                 if (!fBreakpointManager.isEnabled()) {
       
  1094                     attrs.put(ICBreakpoint.ENABLED, false);
       
  1095                 }
       
  1096 
       
  1097                 // Modify the breakpoint in all the target contexts
       
  1098                 getExecutor().execute( new DsfRunnable() {
       
  1099                     public void run() {
       
  1100 
       
  1101                         // If the breakpoint is currently being updated, queue the request and exit
       
  1102                         if (fPendingRequests.contains(breakpoint)) {
       
  1103                             fPendingBreakpoints.add(breakpoint);
       
  1104                             return;
       
  1105                         }
       
  1106 
       
  1107                         // Keep track of the updates
       
  1108                         final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
       
  1109                             @Override
       
  1110                             protected void handleCompleted() {
       
  1111 
       
  1112                                 if (!isSuccess()) {
       
  1113                                     if (getStatus().getSeverity() == IStatus.ERROR) {
       
  1114                                         GdbPlugin.getDefault().getLog().log(getStatus());
       
  1115                                     }
       
  1116                                 }
       
  1117 
       
  1118                                 // Indicate that the pending request has completed
       
  1119                                 fPendingRequests.remove(breakpoint);
       
  1120 
       
  1121                                 // Process the next pending update for this breakpoint
       
  1122                                 if (fPendingBreakpoints.contains(breakpoint)) {
       
  1123                                     fPendingBreakpoints.remove(breakpoint);
       
  1124                                     breakpointChanged(breakpoint, delta);
       
  1125                                 }
       
  1126                             }
       
  1127                         };
       
  1128                         countingRm.setDoneCount(fPlatformBPs.size());
       
  1129 
       
  1130                         // Mark the breakpoint as being updated and go
       
  1131                         fPendingRequests.add(breakpoint);
       
  1132                         
       
  1133                         // Modify the breakpoint in all the execution contexts
       
  1134                         for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
       
  1135                             determineDebuggerPath(dmc, attrs,
       
  1136                                 new RequestMonitor(getExecutor(), countingRm) {
       
  1137                                     @Override
       
  1138                                     protected void handleSuccess() {
       
  1139                                         modifyBreakpoint(dmc, (ICBreakpoint) breakpoint, attrs, delta, new RequestMonitor(getExecutor(), countingRm));
       
  1140                                     }
       
  1141                                  });
       
  1142                         }
       
  1143                     }
       
  1144                 });
       
  1145             } catch (CoreException e) {
       
  1146             } catch (RejectedExecutionException e) {
       
  1147             }
       
  1148         }
       
  1149     }
       
  1150 
       
  1151     /* (non-Javadoc)
       
  1152      * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
       
  1153      */
       
  1154     public void breakpointRemoved(final IBreakpoint breakpoint, IMarkerDelta delta) {
       
  1155 
       
  1156         if (supportsBreakpoint(breakpoint)) {
       
  1157             try {
       
  1158                 getExecutor().execute(new DsfRunnable() {
       
  1159                     public void run() {
       
  1160                         CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
       
  1161                             @Override
       
  1162                             protected void handleError() {
       
  1163                                 if (getStatus().getSeverity() == IStatus.ERROR) {
       
  1164                                     GdbPlugin.getDefault().getLog().log(getStatus());
       
  1165                                 }
       
  1166                             }
       
  1167                         };
       
  1168                         countingRm.setDoneCount(fPlatformBPs.size());
       
  1169 
       
  1170                         // Remove the breakpoint in all the execution contexts
       
  1171                         for (IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
       
  1172                             if (fPlatformBPs.get(dmc).containsKey(breakpoint)) {
       
  1173                                 uninstallBreakpoint(dmc, (ICBreakpoint) breakpoint, countingRm);
       
  1174                             }
       
  1175                         }
       
  1176                     }
       
  1177                 });
       
  1178             } catch (RejectedExecutionException e) {
       
  1179             }
       
  1180         }
       
  1181     }
       
  1182 
       
  1183     ///////////////////////////////////////////////////////////////////////////
       
  1184     // IServiceEventListener
       
  1185     ///////////////////////////////////////////////////////////////////////////
       
  1186 
       
  1187     //-------------------------------------------------------------------------
       
  1188     // Breakpoints
       
  1189     //-------------------------------------------------------------------------
       
  1190 
       
  1191     @DsfServiceEventHandler
       
  1192     public void eventDispatched(BreakpointAddedEvent e) {
       
  1193     	// Nothing to do - already handled by breakpointAdded()
       
  1194     }
       
  1195 
       
  1196     @DsfServiceEventHandler
       
  1197     public void eventDispatched(BreakpointUpdatedEvent e) {
       
  1198     	// Nothing to do - already handled by breakpointChanged()
       
  1199     }
       
  1200 
       
  1201     @DsfServiceEventHandler
       
  1202     public void eventDispatched(BreakpointRemovedEvent e) {
       
  1203     	// Nothing to do - already handled by breakpointRemoved()
       
  1204     }
       
  1205 
       
  1206     /*
       
  1207      * When a watchpoint goes out of scope, it is automatically removed from
       
  1208      * the back-end. To keep our internal state synchronized, we have to
       
  1209      * remove it from our breakpoints maps.
       
  1210      * Unfortunately, GDB doesn't generate the correct event...
       
  1211      */
       
  1212     @DsfServiceEventHandler
       
  1213     public void eventDispatched(MIWatchpointScopeEvent e) {
       
  1214     }
       
  1215 
       
  1216     //-------------------------------------------------------------------------
       
  1217     // Breakpoint actions
       
  1218     //-------------------------------------------------------------------------
       
  1219 
       
  1220 	@DsfServiceEventHandler 
       
  1221     public void eventDispatched(SuspendedEvent e) {
       
  1222 
       
  1223 		if (e.getMIEvent() instanceof MIBreakpointHitEvent) {
       
  1224 			MIBreakpointHitEvent evt = (MIBreakpointHitEvent) e.getMIEvent();
       
  1225 	        performBreakpointAction(evt.getDMContext(), evt.getNumber());
       
  1226 	        return;
       
  1227 		}
       
  1228 
       
  1229 		if (e.getMIEvent() instanceof MIWatchpointTriggerEvent) {
       
  1230 			MIWatchpointTriggerEvent evt = (MIWatchpointTriggerEvent) e.getMIEvent();
       
  1231 	        performBreakpointAction(evt.getDMContext(), evt.getNumber());
       
  1232 	        return;
       
  1233 		}
       
  1234 	}
       
  1235 
       
  1236     private void performBreakpointAction(final IDMContext context, int number) {
       
  1237         // Identify the platform breakpoint
       
  1238         final ICBreakpoint breakpoint = findPlatformBreakpoint(number);
       
  1239 
       
  1240         // Perform the actions asynchronously (otherwise we can have a deadlock...)
       
  1241         new Job("Breakpoint action") { //$NON-NLS-1$
       
  1242             { setSystem(true); }
       
  1243             @Override
       
  1244             protected IStatus run(IProgressMonitor monitor) {
       
  1245                 fBreakpointActionManager.executeActions(breakpoint, new BreakpointActionAdapter(getExecutor(), getServicesTracker(), context));
       
  1246                 return Status.OK_STATUS;
       
  1247             };
       
  1248         }.schedule();
       
  1249     }
       
  1250 
       
  1251     // Helper function to locate the platform breakpoint corresponding
       
  1252     // to the target breakpoint/watchpoint that was just hit
       
  1253 
       
  1254     // FIXME: (Bug228703) Need a way to identify the correct context where the BP was hit
       
  1255     private ICBreakpoint findPlatformBreakpoint(int targetBreakpointID) {
       
  1256         Set<IBreakpointsTargetDMContext> targets = fTargetBPs.keySet();
       
  1257         for (IBreakpointsTargetDMContext target : targets) {
       
  1258             Map<IBreakpointDMContext, ICBreakpoint> bps = fTargetBPs.get(target);
       
  1259             Set<IBreakpointDMContext> contexts = bps.keySet();
       
  1260             for (IBreakpointDMContext context : contexts) {
       
  1261                 if (context instanceof MIBreakpointDMContext) {
       
  1262                     MIBreakpointDMContext ctx = (MIBreakpointDMContext) context;
       
  1263                     if (ctx.getReference() == targetBreakpointID) {
       
  1264                         return bps.get(context);
       
  1265                     }
       
  1266                 }
       
  1267             }
       
  1268         }
       
  1269         return null;
       
  1270     }
       
  1271 
       
  1272     //-------------------------------------------------------------------------
       
  1273     // Session exit
       
  1274     //-------------------------------------------------------------------------
       
  1275 
       
  1276     /**
       
  1277      * @since 1.1
       
  1278      * @nooverride This method is not intended to be re-implemented or extended by clients.
       
  1279      * @noreference This method is not intended to be referenced by clients.
       
  1280      */
       
  1281     @DsfServiceEventHandler
       
  1282     public void eventDispatched(ICommandControlShutdownDMEvent e) {
       
  1283         terminated();
       
  1284     }
       
  1285 
       
  1286     private void terminated() {
       
  1287     	// Reset the breakpoint install count
       
  1288     	for (IBreakpointsTargetDMContext ctx : fPlatformBPs.keySet()) {
       
  1289     		Map<ICBreakpoint, Map<String, Object>> breakpoints = fPlatformBPs.get(ctx);
       
  1290             clearBreakpointStatus(breakpoints.keySet().toArray(new ICBreakpoint[breakpoints.size()]), ctx);
       
  1291     	}
       
  1292     	// This will prevent Shutdown() from trying to remove bps from a
       
  1293     	// backend that has already shutdown
       
  1294         fPlatformBPs.clear();
       
  1295     }
       
  1296 
       
  1297     ///////////////////////////////////////////////////////////////////////////
       
  1298     // Breakpoint status handling functions
       
  1299     ///////////////////////////////////////////////////////////////////////////
       
  1300 
       
  1301     /**
       
  1302      * @param bps
       
  1303      */
       
  1304     private void clearBreakpointStatus(final ICBreakpoint[] bps, final IBreakpointsTargetDMContext ctx)
       
  1305     {
       
  1306         new Job("Clear Breakpoints Status") { //$NON-NLS-1$
       
  1307             @Override
       
  1308             protected IStatus run(IProgressMonitor monitor) {
       
  1309                 IWorkspaceRunnable wr = new IWorkspaceRunnable() {
       
  1310                     public void run(IProgressMonitor monitor) throws CoreException {
       
  1311                     	// For every platform breakpoint that has at least one target breakpoint installed
       
  1312                     	// we must decrement the install count, for every target breakpoint.
       
  1313                     	// Note that we cannot simply call resetInstallCount() because another
       
  1314                     	// launch may be using the same platform breakpoint.
       
  1315                     	Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpoints = fBreakpointIDs.get(ctx);
       
  1316                     	for (ICBreakpoint breakpoint : breakpoints.keySet()) {
       
  1317                     		Vector<IBreakpointDMContext> targetBps = breakpoints.get(breakpoint);
       
  1318                     		for (int i=0; i<targetBps.size(); i++) {
       
  1319                     			breakpoint.decrementInstallCount();
       
  1320                     		}
       
  1321                         }
       
  1322                     }
       
  1323                 };
       
  1324 
       
  1325                 // First clear any problem markers
       
  1326                 for (IMarker marker : fBreakpointMarkerProblems.values()) {
       
  1327                 	if (marker != null) {
       
  1328                 		try {
       
  1329 							marker.delete();
       
  1330 						} catch (CoreException e) {
       
  1331 						}
       
  1332                 	}
       
  1333                 }
       
  1334                 fBreakpointMarkerProblems.clear();
       
  1335                 
       
  1336                 // Create the scheduling rule to clear all bp planted.
       
  1337                 ISchedulingRule rule = null;
       
  1338                 List<ISchedulingRule> markerRules = new ArrayList<ISchedulingRule>();
       
  1339                 for (ICBreakpoint bp : bps) {
       
  1340                     IMarker marker = bp.getMarker();
       
  1341                     if (marker != null) {
       
  1342                         ISchedulingRule markerRule =
       
  1343                             ResourcesPlugin.getWorkspace().getRuleFactory().markerRule(
       
  1344                                     marker.getResource());
       
  1345                         if (markerRule == null) {
       
  1346                             markerRules = null;
       
  1347                             break;
       
  1348                         } else {
       
  1349                             markerRules.add(markerRule);
       
  1350                         }
       
  1351                     }
       
  1352                 }
       
  1353                 if (markerRules != null) {
       
  1354                     rule = MultiRule.combine(markerRules.toArray(new ISchedulingRule[markerRules.size()]));
       
  1355                 }
       
  1356 
       
  1357                 try {
       
  1358                     ResourcesPlugin.getWorkspace().run(wr, rule, 0, null);
       
  1359                 } catch (CoreException e) {
       
  1360                     return e.getStatus();
       
  1361                 }
       
  1362                 return Status.OK_STATUS;
       
  1363             }
       
  1364         }.schedule();
       
  1365     }
       
  1366 
       
  1367     ///////////////////////////////////////////////////////////////////////////
       
  1368     // Support functions
       
  1369     ///////////////////////////////////////////////////////////////////////////
       
  1370 
       
  1371     /**
       
  1372      * supportsBreakpoint
       
  1373      * 
       
  1374      * Indicates if it is breakpoint we can deal with. For now, it boils down
       
  1375      * to a CDI breakpoint...
       
  1376      * 
       
  1377      * @param bp
       
  1378      * @return
       
  1379      */
       
  1380     private boolean supportsBreakpoint(IBreakpoint bp) {
       
  1381         if (bp instanceof ICBreakpoint && bp.getModelIdentifier().equals(fDebugModelId)) {
       
  1382             IMarker marker = bp.getMarker();
       
  1383             if (marker != null) {
       
  1384                 return true;
       
  1385             }
       
  1386         }
       
  1387         return false;
       
  1388     }
       
  1389 
       
  1390     /**
       
  1391      * determineDebuggerPath
       
  1392      * 
       
  1393      * Adds the path to the source file to the set of attributes
       
  1394      * (for the debugger).
       
  1395      * 
       
  1396      * @param dmc
       
  1397      * @param attributes
       
  1398      * @param rm
       
  1399      */
       
  1400     private void determineDebuggerPath(IBreakpointsTargetDMContext dmc,
       
  1401             final Map<String, Object> attributes, final RequestMonitor rm)
       
  1402     {
       
  1403         String hostPath = (String) attributes.get(ICBreakpoint.SOURCE_HANDLE);
       
  1404 
       
  1405         if (hostPath != null) {
       
  1406 
       
  1407             ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(dmc, ISourceLookupDMContext.class);
       
  1408             if (srcDmc != null) {
       
  1409                 fSourceLookup.getDebuggerPath(srcDmc, hostPath,
       
  1410                     new DataRequestMonitor<String>(getExecutor(), rm) {
       
  1411                         @Override
       
  1412                         protected void handleSuccess() {
       
  1413                             attributes.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(getData()));
       
  1414                             rm.done();
       
  1415                         }
       
  1416                     });
       
  1417             } else {
       
  1418                 // Source lookup not available for given context, use the host
       
  1419                 // path for the debugger path.
       
  1420                 attributes.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(hostPath));
       
  1421                 rm.done();
       
  1422             }
       
  1423         } else {
       
  1424             // Some types of breakpoints do not require a path
       
  1425             // (e.g. watchpoints)
       
  1426             rm.done();
       
  1427         }
       
  1428     }
       
  1429 
       
  1430     /**
       
  1431      * See bug232415
       
  1432      * 
       
  1433      * @param path	the absolute path to the source file
       
  1434      * @return
       
  1435      */
       
  1436     private String adjustDebuggerPath(String path) {
       
  1437     	String result = path;
       
  1438     	// Make it MinGW-specific
       
  1439     	if (Platform.getOS().startsWith("win")) { //$NON-NLS-1$
       
  1440         	if (!path.startsWith("/")) { //$NON-NLS-1$
       
  1441         		result = path.substring(path.lastIndexOf('\\') + 1);
       
  1442         	}
       
  1443     	}
       
  1444     	return result;
       
  1445     }
       
  1446 
       
  1447     /**
       
  1448      * Determine the set of modified attributes.
       
  1449      * Elementary set operations in full action :-)
       
  1450      * 
       
  1451      * @param oldAttributes
       
  1452      * @param newAttributes
       
  1453      * @return
       
  1454      */
       
  1455     private Map<String, Object> determineAttributesDelta(Map<String, Object> oldAttributes, Map<String, Object> newAttributes) {
       
  1456 
       
  1457         Map<String, Object> delta = new HashMap<String,Object>();
       
  1458 
       
  1459         Set<String> oldKeySet = oldAttributes.keySet();
       
  1460         Set<String> newKeySet = newAttributes.keySet();
       
  1461 
       
  1462         Set<String> commonKeys  = new HashSet<String>(newKeySet); commonKeys.retainAll(oldKeySet);
       
  1463         Set<String> addedKeys   = new HashSet<String>(newKeySet); addedKeys.removeAll(oldKeySet);
       
  1464         Set<String> removedKeys = new HashSet<String>(oldKeySet); removedKeys.removeAll(newKeySet);
       
  1465 
       
  1466         // Add the modified attributes
       
  1467         for (String key : commonKeys) {
       
  1468             if (!(oldAttributes.get(key).equals(newAttributes.get(key))))
       
  1469                 delta.put(key, newAttributes.get(key));
       
  1470         }
       
  1471 
       
  1472         // Add the new attributes
       
  1473         for (String key : addedKeys) {
       
  1474             delta.put(key, newAttributes.get(key));
       
  1475         }
       
  1476 
       
  1477         // Remove the deleted attributes
       
  1478         for (String key : removedKeys) {
       
  1479             delta.put(key, null);
       
  1480         }
       
  1481 
       
  1482         return convertedAttributes(delta);
       
  1483     }
       
  1484 
       
  1485     /**
       
  1486      * Converts ICBreakpoint attributes to IBreakpoints attributes.
       
  1487      * 
       
  1488      * @param cdt_attributes
       
  1489      * @return
       
  1490      */
       
  1491     private Map<String, Object> convertedAttributes(Map<String, Object> cdt_attributes) {
       
  1492 
       
  1493         Map<String,Object> result = new HashMap<String,Object>();
       
  1494 
       
  1495         // IBreakpoint attributes
       
  1496         if (cdt_attributes.containsKey(ATTR_DEBUGGER_PATH))
       
  1497             result.put(MIBreakpoints.FILE_NAME, cdt_attributes.get(ATTR_DEBUGGER_PATH));
       
  1498             
       
  1499         if (cdt_attributes.containsKey(IMarker.LINE_NUMBER))
       
  1500             result.put(MIBreakpoints.LINE_NUMBER, cdt_attributes.get(IMarker.LINE_NUMBER));
       
  1501             
       
  1502         // ICLineBreakpoint attributes
       
  1503         if (cdt_attributes.containsKey(ICLineBreakpoint.FUNCTION))
       
  1504             result.put(MIBreakpoints.FUNCTION, cdt_attributes.get(ICLineBreakpoint.FUNCTION));
       
  1505             
       
  1506         if (cdt_attributes.containsKey(ICLineBreakpoint.ADDRESS))
       
  1507             result.put(MIBreakpoints.ADDRESS, cdt_attributes.get(ICLineBreakpoint.ADDRESS));
       
  1508             
       
  1509         // ICBreakpoint attributes
       
  1510         if (cdt_attributes.containsKey(ICBreakpoint.CONDITION))
       
  1511             result.put(MIBreakpoints.CONDITION, cdt_attributes.get(ICBreakpoint.CONDITION));
       
  1512             
       
  1513         if (cdt_attributes.containsKey(ICBreakpoint.IGNORE_COUNT))
       
  1514             result.put(MIBreakpoints.IGNORE_COUNT, cdt_attributes.get(ICBreakpoint.IGNORE_COUNT));
       
  1515 
       
  1516         if (cdt_attributes.containsKey(ICBreakpoint.ENABLED))
       
  1517             result.put(MIBreakpoints.IS_ENABLED, cdt_attributes.get(ICBreakpoint.ENABLED));
       
  1518 
       
  1519         // ICWatchpoint attributes
       
  1520         if (cdt_attributes.containsKey(ICWatchpoint.EXPRESSION))
       
  1521             result.put(MIBreakpoints.EXPRESSION, cdt_attributes.get(ICWatchpoint.EXPRESSION));
       
  1522 
       
  1523         if (cdt_attributes.containsKey(ICWatchpoint.READ))
       
  1524             result.put(MIBreakpoints.READ, cdt_attributes.get(ICWatchpoint.READ));
       
  1525         
       
  1526         if (cdt_attributes.containsKey(ICWatchpoint.WRITE))
       
  1527             result.put(MIBreakpoints.WRITE, cdt_attributes.get(ICWatchpoint.WRITE));
       
  1528 
       
  1529         // Threads
       
  1530         if (cdt_attributes.containsKey(ATTR_THREAD_FILTER))
       
  1531             result.put(ATTR_THREAD_FILTER, cdt_attributes.get(ATTR_THREAD_FILTER));
       
  1532 
       
  1533         return result;
       
  1534     }
       
  1535 
       
  1536     /**
       
  1537      * Figure out the corresponding number of back-end breakpoints
       
  1538      * Even though the thread IDs are usually integers, they are
       
  1539      * stored as strings in CBreakpoints.
       
  1540      * 
       
  1541      * @param attributes
       
  1542      * @return
       
  1543      */
       
  1544     @SuppressWarnings("unchecked")
       
  1545     private Set<String> getThreads(Map<String, Object> attributes) {
       
  1546         Set<String> threads = (Set<String>) attributes.get(ATTR_THREAD_FILTER);
       
  1547         if (threads == null) {
       
  1548             threads = new HashSet<String>();
       
  1549             threads.add("0");    // Thread 0 means all threads //$NON-NLS-1$
       
  1550         }
       
  1551         return threads;
       
  1552     }
       
  1553 
       
  1554     /**
       
  1555      * Get the list of threads from the platform breakpoint attributes
       
  1556      * 
       
  1557      * @param breakpoint
       
  1558      * @return
       
  1559      */
       
  1560     private Set<String> extractThreads(IBreakpointsTargetDMContext context, ICBreakpoint breakpoint) {
       
  1561         Set<String> results = new HashSet<String>();
       
  1562 
       
  1563         // Find the ancestor
       
  1564         List<IExecutionDMContext[]> threads = new ArrayList<IExecutionDMContext[]>(1);
       
  1565 
       
  1566         try {
       
  1567             // Retrieve the targets
       
  1568             IDsfBreakpointExtension filterExtension = getFilterExtension(breakpoint);
       
  1569             IContainerDMContext[] targets = filterExtension.getTargetFilters();
       
  1570 
       
  1571             // If no target is present, breakpoint applies to all.
       
  1572             if (targets.length == 0) {
       
  1573                 results.add("0"); //$NON-NLS-1$    
       
  1574                 return results;
       
  1575             }
       
  1576 
       
  1577             // Extract the thread IDs (if there is none, we are covered)
       
  1578             for (IContainerDMContext ctxt : targets) {
       
  1579                 if (DMContexts.isAncestorOf(ctxt, context)) {
       
  1580                     threads.add(filterExtension.getThreadFilters(ctxt));
       
  1581                 }
       
  1582             }
       
  1583         } catch (CoreException e1) {
       
  1584         }
       
  1585 
       
  1586         if (supportsThreads(breakpoint)) {
       
  1587             for (IExecutionDMContext[] targetThreads : threads) {
       
  1588                 if (targetThreads != null) {
       
  1589                     for (IExecutionDMContext thread : targetThreads) {
       
  1590                         if (thread instanceof IMIExecutionDMContext) {
       
  1591                         	IMIExecutionDMContext dmc = (IMIExecutionDMContext) thread;
       
  1592                             results.add(((Integer) dmc.getThreadId()).toString());
       
  1593                         }
       
  1594                     }
       
  1595                 } else {
       
  1596                     results.add("0"); //$NON-NLS-1$    
       
  1597                     break;
       
  1598                 }
       
  1599             }
       
  1600         } else {
       
  1601             results.add("0"); //$NON-NLS-1$
       
  1602         }
       
  1603 
       
  1604         return results;
       
  1605     }
       
  1606 
       
  1607     ///////////////////////////////////////////////////////////////////////////
       
  1608     // Non-generic (MI-specific) functions
       
  1609     ///////////////////////////////////////////////////////////////////////////
       
  1610 
       
  1611     /**
       
  1612      * Create a target breakpoint from an ICBreakpoint
       
  1613      * 
       
  1614      * @param breakpoint
       
  1615      * @param attributes
       
  1616      * @return
       
  1617      */
       
  1618     protected Map<String,Object> convertToTargetBreakpoint(ICBreakpoint breakpoint, Map<String,Object> attributes) {
       
  1619 
       
  1620         Map<String, Object> properties = new HashMap<String, Object>();
       
  1621 
       
  1622         if (breakpoint instanceof ICWatchpoint) {
       
  1623             // Convert the CDI watchpoint to an IBreakpoint
       
  1624             properties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.WATCHPOINT);
       
  1625             properties.put(MIBreakpoints.EXPRESSION,      attributes.get(ICWatchpoint.EXPRESSION));
       
  1626             properties.put(MIBreakpoints.READ,            attributes.get(ICWatchpoint.READ));
       
  1627             properties.put(MIBreakpoints.WRITE,           attributes.get(ICWatchpoint.WRITE));
       
  1628         }
       
  1629         else if (breakpoint instanceof ICLineBreakpoint) {
       
  1630             // Convert the CDI breakpoint to an IBreakpoint
       
  1631             properties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
       
  1632             properties.put(MIBreakpoints.FILE_NAME,       attributes.get(ATTR_DEBUGGER_PATH));
       
  1633             properties.put(MIBreakpoints.LINE_NUMBER,     attributes.get(IMarker.LINE_NUMBER));
       
  1634             properties.put(MIBreakpoints.FUNCTION,        attributes.get(ICLineBreakpoint.FUNCTION));
       
  1635             properties.put(MIBreakpoints.ADDRESS,         attributes.get(ICLineBreakpoint.ADDRESS));
       
  1636         } else {
       
  1637         	// catchpoint?
       
  1638         }
       
  1639 
       
  1640         // Common fields
       
  1641         properties.put(MIBreakpoints.CONDITION,           attributes.get(ICBreakpoint.CONDITION));
       
  1642         properties.put(MIBreakpoints.IGNORE_COUNT,        attributes.get(ICBreakpoint.IGNORE_COUNT));
       
  1643         properties.put(MIBreakpoints.IS_ENABLED,          attributes.get(ICBreakpoint.ENABLED));
       
  1644         properties.put(MIBreakpointDMData.THREAD_ID,      attributes.get(ATTR_THREAD_ID));
       
  1645 
       
  1646         // Adjust for "skip-all"
       
  1647         if (!fBreakpointManager.isEnabled()) {
       
  1648             properties.put(MIBreakpoints.IS_ENABLED, false);
       
  1649         }
       
  1650 
       
  1651         return properties;
       
  1652     }
       
  1653 
       
  1654     /**
       
  1655      * Determine if the modified attributes necessitate
       
  1656      * a breakpoint removal/re-installation
       
  1657      * 
       
  1658      * @param delta
       
  1659      * @return
       
  1660      */
       
  1661     protected boolean needsResinstallation(Map<String,Object> delta) {
       
  1662         
       
  1663         // Check if there is any modified attribute
       
  1664         if (delta == null)
       
  1665             return false;
       
  1666 
       
  1667         // Check the "critical" attributes
       
  1668         if (delta.containsKey(ATTR_DEBUGGER_PATH)            // File name
       
  1669         ||  delta.containsKey(MIBreakpoints.LINE_NUMBER)     // Line number
       
  1670         ||  delta.containsKey(MIBreakpoints.FUNCTION)        // Function name
       
  1671         ||  delta.containsKey(MIBreakpoints.ADDRESS)         // Absolute address
       
  1672         ||  delta.containsKey(ATTR_THREAD_FILTER)            // Thread ID
       
  1673         ||  delta.containsKey(MIBreakpoints.EXPRESSION)      // Watchpoint expression
       
  1674         ||  delta.containsKey(MIBreakpoints.READ)            // Watchpoint type
       
  1675         ||  delta.containsKey(MIBreakpoints.WRITE)) {        // Watchpoint type
       
  1676             return true;
       
  1677         }
       
  1678 
       
  1679          return false;
       
  1680     }
       
  1681 
       
  1682     /**
       
  1683      * @param breakpoint
       
  1684      * @param oldValues
       
  1685      */
       
  1686     protected void rollbackAttributes(ICBreakpoint breakpoint, IMarkerDelta oldValues) {
       
  1687 
       
  1688         try {
       
  1689             String new_condition = breakpoint.getCondition();
       
  1690             if (new_condition == null)
       
  1691                 new_condition = NULL_STRING;
       
  1692             String old_condition = (oldValues != null) ? oldValues.getAttribute(ICBreakpoint.CONDITION, NULL_STRING) : NULL_STRING;
       
  1693             if (!old_condition.equals(new_condition)) {
       
  1694                 breakpoint.setCondition(old_condition);
       
  1695             }
       
  1696             else {
       
  1697                 breakpoint.setCondition(NULL_STRING);
       
  1698             }
       
  1699         } catch (CoreException e) {
       
  1700         }
       
  1701     }
       
  1702 
       
  1703     /**
       
  1704      * Indicates if the back-end supports multiple threads for
       
  1705      * this type of breakpoint
       
  1706      * 
       
  1707      * @param breakpoint
       
  1708      */
       
  1709     protected boolean supportsThreads(ICBreakpoint breakpoint) {
       
  1710 
       
  1711         return !(breakpoint instanceof ICWatchpoint);
       
  1712     }
       
  1713 
       
  1714 }
    40 }