/*******************************************************************************
 * Copyright (c) 2012, 2018 Mentor Graphics and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 * 		Mentor Graphics - Initial API and implementation
 * 		Salvatore Culcasi (ST) - Bug 407163 - GDB Console: breakpoint not added with MinGW and gdb
 *      Marc Khouzam (Ericsson) - Update breakpoint handling for GDB >= 7.4 (Bug 389945)
 *      Marc Khouzam (Ericsson) - Support for dynamic printf (Bug 400628)
 *      Jonah Graham (Kichwa Coders) - Bug 317173 - cleanup warnings
 *      Jonah Graham (Kichwa Coders) - Bug 530377 - Corruption of state due to fast events from GDB
 *      Umair Sair (Siemens) - Bug 571161 - MIBreakpointsSynchronizer is broken in certain scenarios
 *******************************************************************************/

package org.eclipse.cdt.dsf.mi.service;

import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.debug.core.CDIDebugModel;
import org.eclipse.cdt.debug.core.breakpointactions.BreakpointActionManager;
import org.eclipse.cdt.debug.core.model.ICAddressBreakpoint;
import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.cdt.debug.core.model.ICBreakpointType;
import org.eclipse.cdt.debug.core.model.ICDynamicPrintf;
import org.eclipse.cdt.debug.core.model.ICFunctionBreakpoint;
import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
import org.eclipse.cdt.debug.core.model.ICTracepoint;
import org.eclipse.cdt.debug.core.model.ICWatchpoint;
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMData;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IDsfBreakpointExtension;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.CollectAction;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.EvaluateAction;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.ITracepointAction;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.TracepointActionManager;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.WhileSteppingAction;
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext;
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager.IMIBreakpointsTrackingListener;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakListInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
import org.eclipse.cdt.dsf.service.AbstractDsfService;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
import org.osgi.framework.BundleContext;

/**
 * Provides synchronization between breakpoints set from outside of the Eclipse
 * breakpoint framework (GDB console, trace files, etc.) and the Breakpoints
 * view.
 * <p>
 * Bug 530377: Prior to fixing 530377, events that arrived from GDB faster than
 * DSF/Eclipse fully processed them could cause the state within the
 * synchronizer and manager to become corrupt. This would happen because it
 * takes multiple DSF stages to complete handling 1 event, so the handling of
 * the next event would become intermingled. That violated many assumptions in
 * the code that the code run in the respective RequestMonitor would be on the
 * same state. This is an unsuprising assumption based on the general idea of
 * DSF as not requiring the normal synchronization primitives as everything is
 * single-threaded. To resolve this problem, there is some code
 * {@link #queueEvent(BreakpointEvent)} that ensures each event is fully
 * processed before the next event starts processing.
 *
 * @since 4.2
 */
public class MIBreakpointsSynchronizer extends AbstractDsfService
		implements IMIBreakpointsTrackingListener, ICachingService {

	// Catchpoint expressions
	private static final String CE_EXCEPTION_CATCH = "exception catch"; //$NON-NLS-1$
	private static final String CE_EXCEPTION_THROW = "exception throw"; //$NON-NLS-1$

	// GDB tracepoint commands
	private static final String TC_COLLECT = "collect "; //$NON-NLS-1$
	private static final String TC_TEVAL = "teval "; //$NON-NLS-1$
	private static final String TC_WHILE_STEPPING = "while-stepping "; //$NON-NLS-1$
	private static final String TC_END = "end"; //$NON-NLS-1$

	private IMICommandControl fConnection;
	private MIBreakpoints fBreakpointsService;
	private MIBreakpointsManager fBreakpointsManager;

	/**
	 * Collection of the target contexts that are being tracked.
	 */
	private Set<IBreakpointsTargetDMContext> fTrackedTargets;

	/**
	 * Collection of breakpoints created from the GDB console or outside of Eclipse.
	 *
	 * Map of breakpoint contexts to Map of breakpoint number (String) to MIBreakpoint
	 */
	private Map<IBreakpointsTargetDMContext, Map<String, MIBreakpoint>> fCreatedTargetBreakpoints;

	/**
	 * Collection of breakpoints deleted from the GDB console or outside of Eclipse
	 */
	private Map<IBreakpointsTargetDMContext, Set<String>> fDeletedTargetBreakpoints;

	/**
	 * Collection of pending breakpoint modifications
	 */
	private Map<IBreakpointsTargetDMContext, Map<String, MIBreakpoint>> fPendingModifications;

	/**
	 * Class to store an event that needs to be performed by the synchronizer
	 *
	 * @see MIBreakpointsSynchronizer class documentation for design comments
	 */
	private static class BreakpointEvent {
		MIBreakpoint created;
		MIBreakpoint modified;
		String deleted;

		static class BreakpointEventSynchronize {
			IBreakpointsTargetDMContext dmc;
			MIBreakListInfo list;
		}

		BreakpointEventSynchronize synchronize;
	}

	/**
	 * List of events that are queued, waiting to be processed.
	 *
	 * @see MIBreakpointsSynchronizer class documentation for design comments
	 */
	private Deque<BreakpointEvent> fBreakpointEvents = new LinkedList<>();

	/**
	 * True if the delayed events processing task is idle. If idle, a new event
	 * should trigger restarting the processing.
	 *
	 * @see MIBreakpointsSynchronizer class documentation for design comments
	 */
	private boolean fEventsIdle = true;

	public MIBreakpointsSynchronizer(DsfSession session) {
		super(session);
		fTrackedTargets = new HashSet<>();
		fCreatedTargetBreakpoints = new HashMap<>();
		fDeletedTargetBreakpoints = new HashMap<>();
		fPendingModifications = new HashMap<>();
	}

	@Override
	protected BundleContext getBundleContext() {
		return GdbPlugin.getBundleContext();
	}

	@Override
	public void initialize(final RequestMonitor rm) {
		super.initialize(new ImmediateRequestMonitor(rm) {
			@Override
			protected void handleSuccess() {
				doInitialize(rm);
			}
		});
	}

	private void doInitialize(final RequestMonitor rm) {
		fConnection = getServicesTracker().getService(IMICommandControl.class);
		fBreakpointsService = getServicesTracker().getService(MIBreakpoints.class);
		fBreakpointsManager = getServicesTracker().getService(MIBreakpointsManager.class);
		if (fConnection == null || fBreakpointsService == null && fBreakpointsManager == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Service is not available")); //$NON-NLS-1$
			rm.done();
			return;
		}
		fBreakpointsManager.addBreakpointsTrackingListener(this);
		getSession().addServiceEventListener(this, null);

		// Register this service
		register(new String[] { MIBreakpointsSynchronizer.class.getName() }, new Hashtable<String, String>());

		rm.done();
	}

	@Override
	public void shutdown(RequestMonitor rm) {
		fTrackedTargets.clear();
		fCreatedTargetBreakpoints.clear();
		fDeletedTargetBreakpoints.clear();
		fPendingModifications.clear();
		fBreakpointEvents.clear();
		getSession().removeServiceEventListener(this);
		MIBreakpointsManager bm = getBreakpointsManager();
		if (bm != null) {
			bm.removeBreakpointsTrackingListener(this);
		}
		unregister();
		super.shutdown(rm);
	}

	/**
	 * Obtain the collection of MI breakpoints created
	 *
	 * @return collection of target breakpoints
	 * @since 5.3
	 */
	protected Collection<MIBreakpoint> getCreatedTargetBreakpoints(IBreakpointsTargetDMContext context) {
		Map<String, MIBreakpoint> map = fCreatedTargetBreakpoints.get(context);
		if (map != null) {
			return map.values();
		}
		return null;
	}

	@Override
	public void breakpointTrackingStarted(IBreakpointsTargetDMContext bpTargetDMC) {
		fTrackedTargets.add(bpTargetDMC);
	}

	@Override
	public void breakpointTrackingStopped(IBreakpointsTargetDMContext bpTargetDMC) {
		fTrackedTargets.remove(bpTargetDMC);
	}

	private IMICommandControl getCommandControl() {
		return fConnection;
	}

	private MIBreakpoints getBreakpointsService() {
		return fBreakpointsService;
	}

	private MIBreakpointsManager getBreakpointsManager() {
		return fBreakpointsManager;
	}

	/**
	 * Queue (and potentially start processing) breakpoint events from GDB.
	 *
	 * @param event
	 *            from GDB that needs to be processed once the synchronizer is idle
	 *            and has completed the previous event.
	 */
	private void queueEvent(BreakpointEvent event) {
		fBreakpointEvents.add(event);
		if (fEventsIdle) {
			runNextEvent();
		}
	}

	private void runNextEvent() {
		fEventsIdle = false;
		BreakpointEvent event = fBreakpointEvents.poll();
		if (event == null) {
			fEventsIdle = true;
			return;
		}

		RequestMonitor rm = new RequestMonitor(getExecutor(), null) {
			@Override
			protected void handleCompleted() {
				runNextEvent();
				super.handleCompleted();
			}
		};

		if (event.created != null) {
			doTargetBreakpointCreated(event.created, rm);
		} else if (event.deleted != null) {
			doTargetBreakpointDeleted(event.deleted, rm);
		} else if (event.modified != null) {
			doTargetBreakpointModified(event.modified, rm);
		} else if (event.synchronize != null) {
			doTargetBreakpointsSynchronized(event.synchronize.dmc, event.synchronize.list, rm);
		} else {
			rm.done();
		}
	}

	/**
	 * The effect of flushing the cache of the synchronizer is to recollect all
	 * breakpoint info from GDB and update the IBreakpoints and MIBreakpointManager
	 * services too.
	 *
	 * Note that an optimization in the number of calls to synchronize can be done, see
	 * synchronize's removeBpsForAllDmcs parameter.
	 */
	@Override
	public void flushCache(IDMContext context) {
		Collection<IBreakpointsTargetDMContext> contexts;
		IBreakpointsTargetDMContext breakpointsTargetDMContext = DMContexts.getAncestorOfType(context,
				IBreakpointsTargetDMContext.class);
		if (breakpointsTargetDMContext != null) {
			contexts = Arrays.asList(breakpointsTargetDMContext);
		} else {
			contexts = getBreakpointsManager().getTrackedBreakpointTargetContexts();
		}

		for (IBreakpointsTargetDMContext bpContext : contexts) {
			synchronize(bpContext, false);
		}
	}

	/**
	 * Synchronize the breakpoint state with the back end. This is done by issuing a
	 * -break-list to the backend and adding that result to the list of queue'd
	 * events from the backend. When this entry in the queue is processed, it
	 * converts itself to a series of new events that represent the difference
	 * between the state in the breakpoint manager and GDB.
	 *
	 * @param bpContext
	 *            context to issue MI Break List on
	 * @param removeBpsForAllDmcs
	 *            If the break list command returns breakpoints for all contexts,
	 *            pass true. If false, the synchronizer assumes only bps not listed
	 *            for bpContext will be removed. This provides an optimization to
	 *            prevent issuing createMIBreakList multiple times that will return
	 *            the same value. (Note that using a CommandCache will not achieve
	 *            the optimization because each call to createMIBreakList is a
	 *            different context.)
	 * @since 5.5
	 */
	protected void synchronize(IBreakpointsTargetDMContext bpContext, boolean removeBpsForAllDmcs) {
		fConnection.queueCommand(fConnection.getCommandFactory().createMIBreakList(bpContext),
				new DataRequestMonitor<MIBreakListInfo>(getExecutor(), null) {
					@Override
					protected void handleSuccess() {
						BreakpointEvent event = new BreakpointEvent();
						event.synchronize = new BreakpointEvent.BreakpointEventSynchronize();
						event.synchronize.dmc = removeBpsForAllDmcs ? null : bpContext;
						event.synchronize.list = getData();
						queueEvent(event);
					}
				});
	}

	private void doTargetBreakpointsSynchronized(IBreakpointsTargetDMContext breakpointsContext, MIBreakListInfo data,
			RequestMonitor rm) {
		final MIBreakpointsManager bm = getBreakpointsManager();
		Map<IBreakpointsTargetDMContext, Map<IBreakpointDMContext, ICBreakpoint>> bpToPlatformMaps = bm
				.getBPToPlatformMaps();
		Stream<IBreakpointDMContext> breakpointsKnownToManager = bpToPlatformMaps.entrySet().stream()
				.flatMap(m -> m.getValue().keySet().stream());
		Collector<MIBreakpointDMContext, ?, Map<IBreakpointsTargetDMContext, Set<String>>> collector = Collectors.toMap(
				(MIBreakpointDMContext dmc) -> DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class),
				(MIBreakpointDMContext dmc) -> new HashSet<>(Collections.singleton(dmc.getReference())),
				(a, b) -> Stream.concat(a.stream(), b.stream()).collect(Collectors.toCollection(HashSet::new)));
		Map<IBreakpointsTargetDMContext, Set<String>> numbersKnownToManager = breakpointsKnownToManager
				.filter(MIBreakpointDMContext.class::isInstance).map(MIBreakpointDMContext.class::cast)
				.collect(collector);

		for (MIBreakpoint miBpt : data.getMIBreakpoints()) {
			String number = miBpt.getNumber();

			boolean found = false;
			for (Set<String> bpNumbers : numbersKnownToManager.values())
				if (bpNumbers.remove(number))
					found = true;

			BreakpointEvent event = new BreakpointEvent();
			if (found)
				event.modified = miBpt;
			else
				event.created = miBpt;
			fBreakpointEvents.addFirst(event);
		}

		for (Entry<IBreakpointsTargetDMContext, Set<String>> entry : numbersKnownToManager.entrySet()) {
			IBreakpointsTargetDMContext dmc = entry.getKey();
			for (String number : entry.getValue())
				if (number != null && !number.isEmpty()
						&& (breakpointsContext == null || breakpointsContext.equals(dmc))) {
					BreakpointEvent event = new BreakpointEvent();
					event.deleted = number;
					fBreakpointEvents.addFirst(event);
				}
		}

		rm.done();
	}

	public void targetBreakpointCreated(final MIBreakpoint miBpt) {
		BreakpointEvent event = new BreakpointEvent();
		event.created = miBpt;
		queueEvent(event);
	}

	private void doTargetBreakpointCreated(final MIBreakpoint miBpt, RequestMonitor rm) {
		if (isCatchpoint(miBpt)) {
			rm.done();
			return;
		}
		MIBreakpoints breakpointsService = getBreakpointsService();
		final MIBreakpointsManager bm = getBreakpointsManager();
		if (breakpointsService == null || bm == null) {
			rm.done();
			return;
		}

		final IBreakpointsTargetDMContext bpTargetDMC = getBreakpointsTargetContext(miBpt);
		if (bpTargetDMC == null) {
			rm.done();
			return;
		}

		// Store the target breakpoint data
		Map<String, MIBreakpointDMData> contextBreakpoints = breakpointsService.getBreakpointMap(bpTargetDMC);
		if (contextBreakpoints == null) {
			contextBreakpoints = breakpointsService.createNewBreakpointMap(bpTargetDMC);
		}
		contextBreakpoints.put(miBpt.getNumber(), fBreakpointsService.createMIBreakpointDMData(miBpt));

		// Store the created target breakpoint to prevent setting it again on the target
		// when addBreakpoint() is called.
		Map<String, MIBreakpoint> targetMap = fCreatedTargetBreakpoints.get(bpTargetDMC);
		if (targetMap == null) {
			targetMap = new HashMap<>();
			fCreatedTargetBreakpoints.put(bpTargetDMC, targetMap);
		}
		targetMap.put(miBpt.getNumber(), miBpt);

		// Convert the debug info file path into the file path in the local file system
		String debuggerPath = getFileName(miBpt);
		getSource(bpTargetDMC, debuggerPath, new DataRequestMonitor<String>(getExecutor(), rm) {
			@Override
			@ConfinedToDsfExecutor("fExecutor")
			protected void handleSuccess() {
				String fileName = getData();
				if (fileName == null) {
					fileName = getFileName(miBpt);
				}
				// Try to find matching platform breakpoint
				ICBreakpoint plBpt = getPlatformBreakpoint(miBpt, fileName);
				String threadId = miBpt.getThreadId();
				boolean isThreadSpecific = threadId != null && !threadId.isEmpty() && !"0".equals(threadId); //$NON-NLS-1$
				try {
					if (plBpt == null) {
						// If matching platform breakpoint doesn't exist create a new one
						plBpt = createPlatformBreakpoint(fileName, miBpt);
						// If the target breakpoint is thread specific, update thread filters
						if (isThreadSpecific) {
							setThreadSpecificBreakpoint(plBpt, miBpt);
						}
						doTargetBreakpointCreatedSync(miBpt, bpTargetDMC, plBpt);
						delayDone(100, rm);
						return;
					} else {
						// The corresponding platform breakpoint already exists.
						// If the breakpoint tracking has already started we need
						// to notify MIBreakpointsManager which will increment its
						// install count.
						// Otherwise the breakpoint will be processed as an initial
						// breakpoint when the breakpoint tracking starts.
						if (isBreakpointTargetTracked(bpTargetDMC)) {
							// If the target breakpoint is thread specific, update thread filters
							if (isThreadSpecific) {
								setThreadSpecificBreakpoint(plBpt, miBpt);
							}

							ICBreakpoint plBpt2 = plBpt;
							bm.breakpointAdded(plBpt2, miBpt, new RequestMonitor(getExecutor(), rm) {
								@Override
								protected void handleCompleted() {
									doTargetBreakpointCreatedSync(miBpt, bpTargetDMC, plBpt2);
									rm.done();
								}
							});
							return;
						} else {
							doTargetBreakpointCreatedSync(miBpt, bpTargetDMC, plBpt);
							rm.done();
							return;
						}
					}
				} catch (CoreException e) {
					GdbPlugin.log(getStatus());
				}
				rm.done();
				return;
			}

		});
	}

	private void doTargetBreakpointCreatedSync(final MIBreakpoint miBpt, final IBreakpointsTargetDMContext bpTargetDMC,
			ICBreakpoint plBpt) {
		// Make sure the platform breakpoint's parameters are synchronized
		// with the target breakpoint.
		Map<String, MIBreakpoint> map = fPendingModifications.get(bpTargetDMC);
		if (map != null) {
			MIBreakpoint mod = map.remove(miBpt.getNumber());
			if (mod != null) {
				targetBreakpointModified(bpTargetDMC, plBpt, mod);
			}
		} else {
			targetBreakpointModified(bpTargetDMC, plBpt, miBpt);
		}
	}

	/**
	 * Some operations that are passed to platform require a number or delays before
	 * they complete. The reason is that the platform code will retrigger DSF code
	 * and continue updating state. Ideally there would be completion monitors for
	 * the platform operations, but that is not available. Use this method to delay
	 * calling .done() until at least delayExecutorCycles cycles of the executor
	 * have run.
	 *
	 * @param delayExecutorCycles
	 * @param rm
	 */
	private void delayDone(int delayExecutorCycles, RequestMonitor rm) {
		getExecutor().execute(() -> {
			int remaining = delayExecutorCycles - 1;
			if (remaining < 0) {
				rm.done();
			} else {
				delayDone(remaining, rm);
			}
		});
	}

	/**
	 * @since 5.0
	 */
	public void targetBreakpointDeleted(final String id) {
		BreakpointEvent event = new BreakpointEvent();
		event.deleted = id;
		queueEvent(event);
	}

	private void doTargetBreakpointDeleted(final String id, RequestMonitor rm) {
		MIBreakpoints breakpointsService = getBreakpointsService();
		final MIBreakpointsManager bm = getBreakpointsManager();
		if (breakpointsService == null || bm == null) {
			rm.done();
			return;
		}
		final IBreakpointsTargetDMContext bpTargetDMC = breakpointsService.getBreakpointTargetContext(id);
		if (bpTargetDMC != null) {
			final MIBreakpointDMContext bpDMC = new MIBreakpointDMContext(breakpointsService,
					new IDMContext[] { bpTargetDMC }, id);
			breakpointsService.getBreakpointDMData(bpDMC, new DataRequestMonitor<IBreakpointDMData>(getExecutor(), rm) {
				@Override
				@ConfinedToDsfExecutor("fExecutor")
				protected void handleSuccess() {
					if (!(getData() instanceof MIBreakpointDMData)) {
						rm.done();
						return;
					}
					MIBreakpointDMData data = (MIBreakpointDMData) getData();
					if (MIBreakpoints.CATCHPOINT.equals(data.getBreakpointType())) {
						rm.done();
						return;
					}

					IBreakpoint plBpt = bm.findPlatformBreakpoint(bpDMC);
					if (plBpt instanceof ICBreakpoint) {
						Set<String> set = fDeletedTargetBreakpoints.get(bpTargetDMC);
						if (set == null) {
							set = new HashSet<>();
							fDeletedTargetBreakpoints.put(bpTargetDMC, set);
						}
						set.add(id);

						try {
							String threadId = data.getThreadId();
							if (!threadId.equals("0")) { //$NON-NLS-1$
								IDsfBreakpointExtension bpExtension = fBreakpointsManager
										.getFilterExtension((ICBreakpoint) plBpt);

								IMIProcesses processes = getServicesTracker().getService(IMIProcesses.class);
								if (processes == null) {
									rm.done();
									return;
								}

								IContainerDMContext contDMC = processes.createContainerContextFromThreadId(
										getCommandControl().getContext(), data.getThreadId());
								if (contDMC == null) {
									rm.done();
									return;
								}

								IExecutionDMContext[] execDMCs = bpExtension.getThreadFilters(contDMC);
								List<IExecutionDMContext> list = new ArrayList<>(execDMCs.length);
								for (IExecutionDMContext c : execDMCs) {
									if (c instanceof IMIExecutionDMContext
											&& !((IMIExecutionDMContext) c).getThreadId().equals(threadId)) {
										list.add(c);
									}
								}
								if (!list.isEmpty()) {
									bpExtension.setThreadFilters(list.toArray(new IExecutionDMContext[list.size()]));
									rm.done();
									return;
								} else {
									bm.uninstallBreakpoint(bpTargetDMC, (ICBreakpoint) plBpt,
											new RequestMonitor(getExecutor(), rm));
									return;
								}
							} else {
								bm.uninstallBreakpoint(bpTargetDMC, (ICBreakpoint) plBpt,
										new RequestMonitor(getExecutor(), rm));
								return;
							}
						} catch (CoreException e) {
							GdbPlugin.log(e.getStatus());
						}
					}
					rm.done();
				}
			});

		} else {
			rm.done();
		}
	}

	public void targetBreakpointModified(final MIBreakpoint miBpt) {
		BreakpointEvent event = new BreakpointEvent();
		event.modified = miBpt;
		queueEvent(event);
	}

	/**
	 * Find the platform breakpoint, returning it, if it exists via the DRM. If the
	 * drm's data is null, it has not been found.
	 */
	private void findPlatformBreakpoint(final MIBreakpoint miBpt, DataRequestMonitor<IBreakpoint> drm) {
		MIBreakpoints breakpointsService = getBreakpointsService();
		final MIBreakpointsManager bm = getBreakpointsManager();
		if (breakpointsService != null && bm != null) {
			final IBreakpointsTargetDMContext bpTargetDMC = getBreakpointsTargetContext(miBpt);
			if (bpTargetDMC == null) {
				drm.done((IBreakpoint) null);
				return;
			}
			final Map<String, MIBreakpointDMData> contextBreakpoints = breakpointsService.getBreakpointMap(bpTargetDMC);
			if (contextBreakpoints == null) {
				drm.done((IBreakpoint) null);
				return;
			}
			IBreakpoint b = bm.findPlatformBreakpoint(
					new MIBreakpointDMContext(breakpointsService, new IDMContext[] { bpTargetDMC }, miBpt.getNumber()));
			if (b != null) {
				drm.done(b);
			} else {
				// Convert the debug info file path into the file path in the local file system
				String debuggerPath = getFileName(miBpt);
				getSource(bpTargetDMC, debuggerPath, new DataRequestMonitor<String>(getExecutor(), drm) {
					@Override
					@ConfinedToDsfExecutor("fExecutor")
					protected void handleSuccess() {
						String fileName = getData();
						if (fileName == null) {
							fileName = getFileName(miBpt);
						}
						// Try to find matching platform breakpoint
						ICBreakpoint plBpt = getPlatformBreakpoint(miBpt, fileName);
						drm.done(plBpt);
					}
				});
			}
		} else {
			drm.done((ICBreakpoint) null);
		}
	}

	private void doTargetBreakpointModified(final MIBreakpoint miBpt, RequestMonitor rm) {
		if (isCatchpoint(miBpt)) {
			rm.done();
			return;
		}

		findPlatformBreakpoint(miBpt, new DataRequestMonitor<IBreakpoint>(getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				IBreakpointsTargetDMContext bpTargetDMC = getBreakpointsTargetContext(miBpt);
				if (bpTargetDMC == null) {
					rm.done();
					return;
				}

				IBreakpoint breakpoint = getData();
				if (!(breakpoint instanceof ICBreakpoint)) {
					// Platform breakpoint hasn't been created yet. Store the latest
					// modification data, it will be picked up later.
					Map<String, MIBreakpoint> map = fPendingModifications.get(bpTargetDMC);
					if (map == null) {
						map = new HashMap<>();
						fPendingModifications.put(bpTargetDMC, map);
					}
					map.put(miBpt.getNumber(), miBpt);
					rm.done();
				} else {
					ICBreakpoint plBpt = (ICBreakpoint) breakpoint;
					targetBreakpointModified(bpTargetDMC, plBpt, miBpt);
					delayDone(100, rm);
				}
			}
		});
	}

	private void targetBreakpointModified(IBreakpointsTargetDMContext bpTargetDMC, ICBreakpoint plBpt,
			MIBreakpoint miBpt) {
		Map<String, MIBreakpointDMData> contextBreakpoints = getBreakpointsService().getBreakpointMap(bpTargetDMC);
		MIBreakpointDMData oldData = contextBreakpoints.get(miBpt.getNumber());
		contextBreakpoints.put(miBpt.getNumber(), fBreakpointsService.createMIBreakpointDMData(miBpt));
		try {
			if (plBpt.isEnabled() != miBpt.isEnabled()) {
				plBpt.setEnabled(miBpt.isEnabled());
			}
			if (!plBpt.getCondition().equals(miBpt.getCondition())) {
				plBpt.setCondition(miBpt.getCondition());
			}
			// oldData can be null for notifications of breakpoints that are inserted using DSF but
			// not with breakpoint service
			if (oldData != null && oldData.isPending() != miBpt.isPending()) {
				if (miBpt.isPending()) {
					plBpt.decrementInstallCount();
				} else {
					plBpt.incrementInstallCount();
				}
			}
			if (plBpt instanceof ICTracepoint && miBpt.isTracepoint()) {
				ICTracepoint plTpt = (ICTracepoint) plBpt;
				if (plTpt.getPassCount() != miBpt.getPassCount()) {
					// GDB (up to 7.5) doesn't emit notification when the pass count is modified.
					plTpt.setPassCount(miBpt.getPassCount());
				}

				if (!miBpt.getCommands()
						.equals(plBpt.getMarker().getAttribute(BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE))) {
					StringBuilder sb = new StringBuilder();
					boolean first = true;
					String[] commands = miBpt.getCommands().split(TracepointActionManager.TRACEPOINT_ACTION_DELIMITER);
					for (ITracepointAction action : getActionsFromCommands(commands)) {
						if (first) {
							first = false;
						} else {
							sb.append(TracepointActionManager.TRACEPOINT_ACTION_DELIMITER);
						}
						sb.append(action.getName());
					}
					// Target breakpoints and platform breakpoints use the same format
					// to store trace commands. This format is different than the format
					// used by GDB. We need to switch to the platform format to avoid unnecessary
					// modifications of target breakpoints.
					miBpt.setCommands(sb.toString());
					plBpt.getMarker().setAttribute(BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE, sb.toString());
				}
			} else if (plBpt instanceof ICDynamicPrintf && miBpt.isDynamicPrintf()) {
				// Cannot synchronize the string as there is a bug in GDB 7.7 that corrupts it.
				// https://sourceware.org/bugzilla/show_bug.cgi?id=15806
				// If we were to synchronize here, we would overwrite the string defined by
				// the user with the corrupted one!
				// Truth is that we don't need to synchronize the string anyway because there
				// is currently no way to change a dprintf string in GDB; instead a new
				// dprintf must be created.  That means that there will be no =breakpoint-modifed
				// event that indicates a real dprintf string change; only the other fields can
				// change and are handled as any other breakpoint.
				//
				// ICDynamicPrintf plDPrintf = (ICDynamicPrintf)plBpt;
				// if (!plDPrintf.getPrintfString().equals(miBpt.getPrintfString())) {
				// 	plDPrintf.setPrintfString(miBpt.getPrintfString());
				// }
			}
		} catch (CoreException e) {
			if (oldData != null)
				contextBreakpoints.put(miBpt.getNumber(), oldData);
			else
				contextBreakpoints.remove(miBpt.getNumber());
			GdbPlugin.log(e.getStatus());
		}
	}

	private void setThreadSpecificBreakpoint(final ICBreakpoint plBpt, MIBreakpoint miBpt) {

		try {
			IMIProcesses processes = getServicesTracker().getService(IMIProcesses.class);
			if (processes == null) {
				return;
			}
			String threadId = miBpt.getThreadId();
			IContainerDMContext contDMC = processes.createContainerContextFromThreadId(getCommandControl().getContext(),
					threadId);
			if (contDMC == null) {
				return;
			}
			IProcessDMContext procDmc = DMContexts.getAncestorOfType(contDMC, IProcessDMContext.class);
			if (procDmc == null) {
				return;
			}
			IDsfBreakpointExtension bpExtension = fBreakpointsManager.getFilterExtension(plBpt);

			IExecutionDMContext[] execDMCs = bpExtension.getThreadFilters(contDMC);
			if (execDMCs == null) {
				execDMCs = new IExecutionDMContext[0];
			}
			for (IExecutionDMContext execDMC : execDMCs) {
				String ctxThreadId = ((IMIExecutionDMContext) execDMC).getThreadId();
				if (execDMC instanceof IMIExecutionDMContext && ctxThreadId.equals(threadId)) {
					// The platform breakpoint is already restricted to the given thread.
					return;
				}
			}
			IExecutionDMContext[] newExecDMCs = new IExecutionDMContext[execDMCs.length + 1];
			System.arraycopy(execDMCs, 0, newExecDMCs, 0, execDMCs.length);
			newExecDMCs[execDMCs.length] = processes.createExecutionContext(contDMC,
					processes.createThreadContext(procDmc, threadId), threadId);
			bpExtension.setThreadFilters(newExecDMCs);
		} catch (CoreException e) {
			GdbPlugin.log(e);
		}
	}

	private ICBreakpoint getPlatformBreakpoint(MIBreakpoint miBpt, String fileName) {
		for (IBreakpoint b : DebugPlugin.getDefault().getBreakpointManager().getBreakpoints()) {
			if (b instanceof ICBreakpoint) {
				ICBreakpoint cBreakpoint = (ICBreakpoint) b;
				if (isPlatformBreakpoint(cBreakpoint, miBpt, fileName)) {
					return cBreakpoint;
				}
			}
		}
		return null;
	}

	/**
	 * Return true if the target breakpoint is the same as the platform breakpoint.
	 *
	 * Whether breakpoints are considered the same depends on their type and their key attributes, with each type
	 * defining its own key attributes.
	 *
	 * @param platformBreakpoint
	 * @param targetBreakpoint
	 * @param fileName
	 *            source lookup resolved file name. The file name in targetBreakpoint will be the file name as GDB
	 *            understands it, and fileName will be the resolved value as Eclipse (and therefore the platform
	 *            breakpoint) understands it.
	 * @return if platformBreakpoint and targetBreakpoint match
	 * @since 5.3
	 */
	protected boolean isPlatformBreakpoint(ICBreakpoint platformBreakpoint, MIBreakpoint targetBreakpoint,
			String fileName) {
		if (platformBreakpoint instanceof ICTracepoint && targetBreakpoint.isTracepoint()
				&& isPlatformTracepoint((ICTracepoint) platformBreakpoint, targetBreakpoint, fileName)) {
			return true;
		}
		if (platformBreakpoint instanceof ICDynamicPrintf && targetBreakpoint.isDynamicPrintf()
				&& isPlatformDynamicPrintf((ICDynamicPrintf) platformBreakpoint, targetBreakpoint, fileName)) {
			return true;
		}
		if (platformBreakpoint instanceof ICWatchpoint && targetBreakpoint.isWatchpoint()
				&& isPlatformWatchpoint((ICWatchpoint) platformBreakpoint, targetBreakpoint)) {
			return true;
		}
		if (platformBreakpoint instanceof ICLineBreakpoint && !targetBreakpoint.isWatchpoint()
				&& !isCatchpoint(targetBreakpoint) && !targetBreakpoint.isTracepoint()
				&& !targetBreakpoint.isDynamicPrintf()
				&& isPlatformLineBreakpoint((ICLineBreakpoint) platformBreakpoint, targetBreakpoint, fileName)) {
			return true;
		}
		return false;
	}

	private ICBreakpoint createPlatformBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
		ICBreakpoint bp = createPlatformBreakpoint0(fileName, miBpt);
		DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(bp);
		return bp;
	}

	/**
	 * Create the platform breakpoint, but don't register it with breakpoint manager. This method is called when the
	 * synchronizer needs to create a new platform breakpoint for a new breakpoint created by the user in the CLI
	 * interface (in response to =breakpoint-created event).
	 *
	 * If further fine tuning on the created breakpoint is needed, consider overriding
	 * {@link #targetBreakpointCreated(MIBreakpoint)} or even replacing the entire breakpoint synchronizer.
	 *
	 * @param fileName
	 *            the name of the file that breakpoint was inserted into, as determined by source lookup
	 * @param miBpt
	 *            the MI breakpoint created
	 * @return the newly created Platform breakpoint
	 * @throws CoreException
	 * @since 5.3
	 */
	protected ICBreakpoint createPlatformBreakpoint0(String fileName, MIBreakpoint miBpt) throws CoreException {
		if (miBpt.isWatchpoint()) {
			return createPlatformWatchpoint(fileName, miBpt);
		} else if (miBpt.isTracepoint()) {
			return createPlatformTracepoint(fileName, miBpt);
		} else if (miBpt.isDynamicPrintf()) {
			return createPlatformDynamicPrintf(fileName, miBpt);
		} else {
			return createPlatformLocationBreakpoint(fileName, miBpt);
		}
	}

	private ICBreakpoint createPlatformLocationBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
		if (isAddressBreakpoint(miBpt)) {
			return createPlatformAddressBreakpoint(fileName, miBpt);
		} else if (isFunctionBreakpoint(miBpt)) {
			return createPlatformFunctionBreakpoint(fileName, miBpt);
		} else {
			return createPlatformLineBreakpoint(fileName, miBpt);
		}
	}

	private ICBreakpoint createPlatformAddressBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
		IResource resource = getResource(fileName);

		int type = 0;
		if (miBpt.isTemporary()) {
			type |= ICBreakpointType.TEMPORARY;
		}
		if (miBpt.isHardware()) {
			type |= ICBreakpointType.HARDWARE;
		}

		try {
			return CDIDebugModel.createAddressBreakpoint(null, null, resource, type,
					getPlatformAddress(miBpt.getAddress()), miBpt.isEnabled(), miBpt.getIgnoreCount(),
					miBpt.getCondition(), false);
		} catch (NumberFormatException e) {
			throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.getUniqueIdentifier(),
					String.format("Invalid breakpoint address: %s", miBpt.getAddress()))); //$NON-NLS-1$
		}
	}

	private ICBreakpoint createPlatformFunctionTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
		IResource resource = getResource(fileName);

		int type = 0;
		if (miBpt.isTemporary()) {
			type |= ICBreakpointType.TEMPORARY;
		}
		if (miBpt.isHardware()) {
			type |= ICBreakpointType.HARDWARE;
		}

		return CDIDebugModel.createFunctionTracepoint(fileName, resource, type, getFunctionName(miBpt), -1, -1,
				getLineNumber(miBpt), miBpt.isEnabled(), miBpt.getIgnoreCount(), miBpt.getCondition(), false);
	}

	private ICBreakpoint createPlatformLineTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
		IResource resource = getResource(fileName);

		int type = 0;
		if (miBpt.isTemporary()) {
			type |= ICBreakpointType.TEMPORARY;
		}
		if (miBpt.isHardware()) {
			type |= ICBreakpointType.HARDWARE;
		}

		return CDIDebugModel.createLineTracepoint(fileName, resource, type, getLineNumber(miBpt), miBpt.isEnabled(),
				miBpt.getIgnoreCount(), miBpt.getCondition(), false);
	}

	private ICBreakpoint createPlatformTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
		if (isAddressBreakpoint(miBpt)) {
			return createPlatformAddressTracepoint(fileName, miBpt);
		} else if (isFunctionBreakpoint(miBpt)) {
			return createPlatformFunctionTracepoint(fileName, miBpt);
		} else {
			return createPlatformLineTracepoint(fileName, miBpt);
		}
	}

	private ICBreakpoint createPlatformAddressTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
		IResource resource = getResource(fileName);

		int type = 0;
		if (miBpt.isTemporary()) {
			type |= ICBreakpointType.TEMPORARY;
		}
		if (miBpt.isHardware()) {
			type |= ICBreakpointType.HARDWARE;
		}

		try {
			return CDIDebugModel.createAddressTracepoint(null, null, resource, type, getLineNumber(miBpt),
					getPlatformAddress(miBpt.getAddress()), miBpt.isEnabled(), miBpt.getIgnoreCount(),
					miBpt.getCondition(), false);
		} catch (NumberFormatException e) {
			throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.getUniqueIdentifier(),
					String.format("Invalid breakpoint address: %s", miBpt.getAddress()))); //$NON-NLS-1$
		}
	}

	/**
	 * Create a new platform breakpoint for the function breakpoint. This method is
	 * called when =breakpoint-created is received from GDB and there is not already
	 * a matching platform breakpoint
	 *
	 * @param fileName
	 *            resolved filename
	 * @param miBpt
	 *            breakpoint info from GDB, must be one for which
	 *            {@link #isFunctionBreakpoint(MIBreakpoint)} returns true.
	 * @return new platform breakpoint
	 * @throws CoreException
	 */
	private ICBreakpoint createPlatformFunctionBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
		IResource resource;
		String resolvedFileName;

		if (userRequestedSpecificFile(miBpt)) {
			resource = getResource(fileName);
			resolvedFileName = fileName;
		} else {
			resource = ResourcesPlugin.getWorkspace().getRoot();
			resolvedFileName = null;
		}

		int type = 0;
		if (miBpt.isTemporary()) {
			type |= ICBreakpointType.TEMPORARY;
		}
		if (miBpt.isHardware()) {
			type |= ICBreakpointType.HARDWARE;
		}

		return CDIDebugModel.createFunctionBreakpoint(resolvedFileName, resource, type, getFunctionName(miBpt), -1, -1,
				getLineNumber(miBpt), miBpt.isEnabled(), miBpt.getIgnoreCount(), miBpt.getCondition(), false);
	}

	/**
	 * If the user inserted the breakpoint with a filename (e.g. "b main.c:main")
	 * then create the breakpoint with that file, otherwise the function breakpoint
	 * should be inserted in the same way as if it was done with the UI "Add
	 * Function Breakpoint (C/C++)".
	 *
	 * @param miBpt
	 *            an MI Breakpoint that is a function breakpoint
	 * @return true if the user specified file and function, false if just a
	 *         function was specified.
	 */
	private boolean userRequestedSpecificFile(MIBreakpoint miBpt) {
		assert isFunctionBreakpoint(miBpt);
		String originalLocation = miBpt.getOriginalLocation();
		return originalLocation != null && originalLocation.contains(":"); //$NON-NLS-1$
	}

	private ICBreakpoint createPlatformLineBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
		IResource resource = getResource(fileName);

		int type = 0;
		if (miBpt.isTemporary()) {
			type |= ICBreakpointType.TEMPORARY;
		}
		if (miBpt.isHardware()) {
			type |= ICBreakpointType.HARDWARE;
		}

		return CDIDebugModel.createLineBreakpoint(fileName, resource, type, getLineNumber(miBpt), miBpt.isEnabled(),
				miBpt.getIgnoreCount(), miBpt.getCondition(), false);
	}

	private ICBreakpoint createPlatformDynamicPrintf(String fileName, MIBreakpoint miBpt) throws CoreException {
		if (isAddressBreakpoint(miBpt)) {
			return createPlatformAddressDynamicPrintf(fileName, miBpt);
		}
		// TODO This is currently causing problems because we think a normal dprintf is a function one
		// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=400628#c16 which says:
		// "synchronization of function dprintf does not work"
		//		else if (isFunctionBreakpoint(miBpt)) {
		//			return createPlatformFunctionDynamicPrintf(fileName, miBpt);
		//		}
		else {
			return createPlatformLineDynamicPrintf(fileName, miBpt);
		}
	}

	private ICBreakpoint createPlatformAddressDynamicPrintf(String fileName, MIBreakpoint miBpt) throws CoreException {
		IResource resource = getResource(fileName);

		int type = 0;
		if (miBpt.isTemporary()) {
			type |= ICBreakpointType.TEMPORARY;
		}
		if (miBpt.isHardware()) {
			type |= ICBreakpointType.HARDWARE;
		}

		try {
			return CDIDebugModel.createAddressDynamicPrintf(null, null, resource, type, getLineNumber(miBpt),
					getPlatformAddress(miBpt.getAddress()), miBpt.isEnabled(), miBpt.getIgnoreCount(),
					miBpt.getCondition(), miBpt.getPrintfString(), false);
		} catch (NumberFormatException e) {
			throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.getUniqueIdentifier(),
					String.format("Invalid breakpoint address: %s", miBpt.getAddress()))); //$NON-NLS-1$
		}
	}

	// Unused, see TODO in createPlatformDynamicPrintf and Bug 400628 Comment 16
	@SuppressWarnings("unused")
	private ICBreakpoint createPlatformFunctionDynamicPrintf(String fileName, MIBreakpoint miBpt) throws CoreException {
		IResource resource = getResource(fileName);

		int type = 0;
		if (miBpt.isTemporary()) {
			type |= ICBreakpointType.TEMPORARY;
		}
		if (miBpt.isHardware()) {
			type |= ICBreakpointType.HARDWARE;
		}

		return CDIDebugModel.createFunctionDynamicPrintf(fileName, resource, type, getFunctionName(miBpt), -1, -1,
				getLineNumber(miBpt), miBpt.isEnabled(), miBpt.getIgnoreCount(), miBpt.getCondition(),
				miBpt.getPrintfString(), false);
	}

	private ICBreakpoint createPlatformLineDynamicPrintf(String fileName, MIBreakpoint miBpt) throws CoreException {
		IResource resource = getResource(fileName);

		int type = 0;
		if (miBpt.isTemporary()) {
			type |= ICBreakpointType.TEMPORARY;
		}
		if (miBpt.isHardware()) {
			type |= ICBreakpointType.HARDWARE;
		}

		return CDIDebugModel.createLineDynamicPrintf(fileName, resource, type, getLineNumber(miBpt), miBpt.isEnabled(),
				miBpt.getIgnoreCount(), miBpt.getCondition(), miBpt.getPrintfString(), false);
	}

	private ICBreakpoint createPlatformWatchpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
		IResource resource = getResource(fileName);

		int type = 0;
		if (miBpt.isTemporary()) {
			type |= ICBreakpointType.TEMPORARY;
		}
		if (miBpt.isHardware()) {
			type |= ICBreakpointType.HARDWARE;
		}

		return CDIDebugModel.createWatchpoint(fileName, resource, type,
				miBpt.isAccessWatchpoint() || miBpt.isWriteWatchpoint(),
				miBpt.isAccessWatchpoint() || miBpt.isReadWatchpoint(), miBpt.getExpression(), miBpt.isEnabled(),
				miBpt.getIgnoreCount(), miBpt.getCondition(), false);
	}

	/**
	 * Retrieve the breakpoint context from the given target breakpoint
	 * @param miBpt target breakpoint
	 * @return breakpoint context, or {@code null} if not available
	 * @since 5.3
	 */
	protected IBreakpointsTargetDMContext getBreakpointsTargetContext(MIBreakpoint miBpt) {
		IMIProcesses processes = getServicesTracker().getService(IMIProcesses.class);
		if (processes == null || getCommandControl() == null) {
			return null;
		}

		// For GDB  < 7.4, each process is its own breakpointTargetDMC so we need to find a the proper process
		// based on the threadId.  For GDB >= 7.4, this does not matter as we'll always end up with the global bpTargetDMC
		String threadId = (miBpt != null) ? miBpt.getThreadId() : null;
		IContainerDMContext contContext = processes.createContainerContextFromThreadId(getCommandControl().getContext(),
				threadId);
		return DMContexts.getAncestorOfType(contContext, IBreakpointsTargetDMContext.class);
	}

	public void getTargetBreakpoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes,
			DataRequestMonitor<MIBreakpoint> rm) {
		Collection<MIBreakpoint> targetBreakpoints = getCreatedTargetBreakpoints(context);
		if (targetBreakpoints == null) {
			rm.done();
			return;
		}
		String type = (String) attributes.get(MIBreakpoints.BREAKPOINT_TYPE);
		if (MIBreakpoints.BREAKPOINT.equals(type)) {
			rm.done(getTargetLineBreakpoint(targetBreakpoints, (String) attributes.get(MIBreakpoints.FILE_NAME),
					(Integer) attributes.get(MIBreakpoints.LINE_NUMBER),
					(String) attributes.get(MIBreakpoints.FUNCTION), (String) attributes.get(MIBreakpoints.ADDRESS),
					(Boolean) attributes.get(MIBreakpointDMData.IS_HARDWARE),
					(Boolean) attributes.get(MIBreakpointDMData.IS_TEMPORARY)));
		} else if (MIBreakpoints.TRACEPOINT.equals(type)) {
			rm.done(getTargetTracepoint(targetBreakpoints, (String) attributes.get(MIBreakpoints.FILE_NAME),
					(Integer) attributes.get(MIBreakpoints.LINE_NUMBER),
					(String) attributes.get(MIBreakpoints.FUNCTION), (String) attributes.get(MIBreakpoints.ADDRESS),
					(Boolean) attributes.get(MIBreakpointDMData.IS_HARDWARE),
					(Boolean) attributes.get(MIBreakpointDMData.IS_TEMPORARY)));
		} else if (MIBreakpoints.DYNAMICPRINTF.equals(type)) {
			rm.done(getTargetDPrintf(targetBreakpoints, (String) attributes.get(MIBreakpoints.FILE_NAME),
					(Integer) attributes.get(MIBreakpoints.LINE_NUMBER),
					(String) attributes.get(MIBreakpoints.FUNCTION), (String) attributes.get(MIBreakpoints.ADDRESS),
					(Boolean) attributes.get(MIBreakpointDMData.IS_HARDWARE),
					(Boolean) attributes.get(MIBreakpointDMData.IS_TEMPORARY)));
		} else if (MIBreakpoints.WATCHPOINT.equals(type)) {
			rm.done(getTargetWatchpoint(targetBreakpoints, (String) attributes.get(MIBreakpoints.EXPRESSION),
					(Boolean) attributes.get(MIBreakpoints.READ), (Boolean) attributes.get(MIBreakpoints.WRITE),
					(Boolean) attributes.get(MIBreakpointDMData.IS_HARDWARE),
					(Boolean) attributes.get(MIBreakpointDMData.IS_TEMPORARY)));
		} else {
			rm.done();
		}
	}

	private MIBreakpoint getTargetLineBreakpoint(Collection<MIBreakpoint> targetBreakpoints, String fileName,
			Integer lineNumber, String function, String address, Boolean isHardware, Boolean isTemporary) {
		for (MIBreakpoint miBpt : targetBreakpoints) {
			if (!miBpt.isWatchpoint() && !isCatchpoint(miBpt) && !miBpt.isTracepoint() && !miBpt.isDynamicPrintf()
					&& compareBreakpointAttributes(miBpt, fileName, lineNumber, function, address, isHardware,
							isTemporary)) {
				return miBpt;
			}
		}
		return null;
	}

	private MIBreakpoint getTargetTracepoint(Collection<MIBreakpoint> targetBreakpoints, String fileName,
			Integer lineNumber, String function, String address, Boolean isHardware, Boolean isTemporary) {
		for (MIBreakpoint miBpt : targetBreakpoints) {
			if (miBpt.isTracepoint() && compareBreakpointAttributes(miBpt, fileName, lineNumber, function, address,
					isHardware, isTemporary)) {
				return miBpt;
			}
		}
		return null;
	}

	private MIBreakpoint getTargetDPrintf(Collection<MIBreakpoint> targetBreakpoints, String fileName,
			Integer lineNumber, String function, String address, Boolean isHardware, Boolean isTemporary) {
		for (MIBreakpoint miBpt : targetBreakpoints) {
			if (miBpt.isDynamicPrintf() && compareBreakpointAttributes(miBpt, fileName, lineNumber, function, address,
					isHardware, isTemporary)) {
				return miBpt;
			}
		}
		return null;
	}

	private MIBreakpoint getTargetWatchpoint(Collection<MIBreakpoint> targetBreakpoints, String expression,
			boolean readAccess, boolean writeAccess, Boolean isHardware, Boolean isTemporary) {
		for (MIBreakpoint miBpt : targetBreakpoints) {
			if (!miBpt.isWatchpoint()) {
				continue;
			}
			if (expression == null || !expression.equals(miBpt.getExpression())) {
				continue;
			}
			if (readAccess && writeAccess && !miBpt.isAccessWatchpoint()) {
				continue;
			}
			if (readAccess && !writeAccess && !miBpt.isReadWatchpoint()) {
				continue;
			}
			if (!readAccess && writeAccess && !miBpt.isWriteWatchpoint()) {
				continue;
			}
			if (!compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary)) {
				continue;
			}
			return miBpt;
		}
		return null;
	}

	private boolean compareBreakpointAttributes(MIBreakpoint miBpt, String fileName, Integer lineNumber,
			String function, String address, Boolean isHardware, Boolean isTemporary) {
		return compareBreakpointLocationAttributes(miBpt, fileName, lineNumber, function, address)
				&& compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary);
	}

	private boolean compareBreakpointLocationAttributes(MIBreakpoint miBpt, String fileName, Integer lineNumber,
			String function, String address) {
		if (isFunctionBreakpoint(miBpt) && (function == null || !function.equals(getFunctionName(miBpt)))) {
			return false;
		}
		if (isAddressBreakpoint(miBpt)
				&& (address == null || !address.equals(getPlatformAddress(miBpt.getAddress()).toHexAddressString()))) {
			return false;
		}
		if (isLineBreakpoint(miBpt)) {
			String miBptFileName = getFileName(miBpt);
			if (fileName == null || miBptFileName == null || !new File(fileName).equals(new File(miBptFileName))) {
				return false;
			}
			if (lineNumber == null || lineNumber.intValue() != getLineNumber(miBpt)) {
				return false;
			}
		}
		return true;
	}

	private boolean compareBreakpointTypeAttributes(MIBreakpoint miBpt, Boolean isHardware, Boolean isTemporary) {
		if ((isHardware == null && miBpt.isHardware())
				|| (isHardware != null && isHardware.booleanValue() != miBpt.isHardware())) {
			return false;
		}
		if ((isTemporary == null && miBpt.isTemporary())
				|| (isTemporary != null && isTemporary.booleanValue() != miBpt.isTemporary())) {
			return false;
		}
		return true;
	}

	public void removeCreatedTargetBreakpoint(IBreakpointsTargetDMContext context, MIBreakpoint miBpt) {
		Map<String, MIBreakpoint> map = fCreatedTargetBreakpoints.get(context);
		if (map != null) {
			map.remove(miBpt.getNumber());
		}
	}

	private boolean isPlatformLineBreakpoint(ICLineBreakpoint plBpt, MIBreakpoint miBpt, String fileName) {
		if (plBpt instanceof ICAddressBreakpoint) {
			return isAddressBreakpoint(miBpt) ? isPlatformAddressBreakpoint((ICAddressBreakpoint) plBpt, miBpt) : false;
		}
		if (plBpt instanceof ICFunctionBreakpoint) {
			return isFunctionBreakpoint(miBpt)
					? isPlatformFunctionBreakpoint((ICFunctionBreakpoint) plBpt, miBpt, fileName)
					: false;
		}
		try {
			if (fileName == null || plBpt.getSourceHandle() == null
					|| !new File(fileName).equals(new File(plBpt.getSourceHandle()))) {
				return false;
			}
			if (plBpt.getLineNumber() != getLineNumber(miBpt)) {
				return false;
			}
			return true;
		} catch (CoreException e) {
			GdbPlugin.log(e.getStatus());
		}
		return false;
	}

	private boolean isPlatformFunctionBreakpoint(ICFunctionBreakpoint plBpt, MIBreakpoint miBpt, String fileName) {
		try {
			if (!Objects.equals(plBpt.getFunction(), getFunctionName(miBpt))) {
				return false;
			}
			if (userRequestedSpecificFile(miBpt)) {
				if (fileName == null || plBpt.getSourceHandle() == null
						|| !new File(fileName).equals(new File(plBpt.getSourceHandle()))) {
					return false;
				}
			} else {
				if (plBpt.getSourceHandle() != null) {
					return false;
				}
			}
			return true;
		} catch (CoreException e) {
			GdbPlugin.log(e.getStatus());
		}
		return false;
	}

	private boolean isPlatformAddressBreakpoint(ICAddressBreakpoint plBpt, MIBreakpoint miBpt) {
		try {
			return (plBpt.getAddress() != null
					&& plBpt.getAddress().equals(getPlatformAddress(miBpt.getAddress()).toHexAddressString()));
		} catch (CoreException e) {
			GdbPlugin.log(e.getStatus());
		}
		return false;
	}

	private boolean isPlatformWatchpoint(ICWatchpoint plBpt, MIBreakpoint miBpt) {
		try {
			if (plBpt.getExpression() != null && plBpt.getExpression().equals(miBpt.getExpression())) {
				if (miBpt.isAccessWatchpoint()) {
					return plBpt.isWriteType() && plBpt.isReadType();
				} else if (miBpt.isReadWatchpoint()) {
					return !plBpt.isWriteType() && plBpt.isReadType();
				} else if (miBpt.isWriteWatchpoint()) {
					return plBpt.isWriteType() && !plBpt.isReadType();
				}
			}
		} catch (CoreException e) {
			GdbPlugin.log(e.getStatus());
		}
		return false;
	}

	private boolean isPlatformTracepoint(ICTracepoint plBpt, MIBreakpoint miBpt, String fileName) {
		return isPlatformLineBreakpoint(plBpt, miBpt, fileName);
	}

	private boolean isPlatformDynamicPrintf(ICDynamicPrintf plBpt, MIBreakpoint miBpt, String fileName) {
		return isPlatformLineBreakpoint(plBpt, miBpt, fileName);
	}

	/** @since 5.0 */
	public boolean isTargetBreakpointDeleted(IBreakpointsTargetDMContext context, String bpId, boolean remove) {
		Set<String> set = fDeletedTargetBreakpoints.get(context);
		if (set != null) {
			return (remove) ? set.remove(bpId) : set.contains(bpId);
		}
		return false;
	}

	/**
	 * Returns the list of tracepoint actions generated from the given command string.
	 * If the corresponding action for a command doesn't exist in TracepointActionManager
	 * the new action is created and added.
	 *
	 * @param commands list of gdb tracepoint commands separated by TracepointActionManager.TRACEPOINT_ACTION_DELIMITER
	 */
	private ITracepointAction[] getActionsFromCommands(String[] commands) {
		List<ITracepointAction> list = new ArrayList<>();
		TracepointActionManager tam = TracepointActionManager.getInstance();
		WhileSteppingAction whileStepping = null;
		List<ITracepointAction> subActions = null;
		for (String command : commands) {
			// Check if an action for this command exists
			boolean found = false;
			for (ITracepointAction action : tam.getActions()) {
				if (command.equals(action.getSummary())) {
					if (whileStepping == null || subActions == null) {
						list.add(action);
					} else {
						subActions.add(action);
					}
					found = true;
					break;
				}
			}
			if (!found) {
				// Create a new action if an action for this command doesn't exists
				ITracepointAction action = null;
				if (command.startsWith(TC_COLLECT)) {
					action = createCollectAction(command.substring(TC_COLLECT.length()));
				} else if (command.startsWith(TC_TEVAL)) {
					action = createEvaluateAction(command.substring(TC_TEVAL.length()));
				} else if (command.startsWith(TC_WHILE_STEPPING)) {
					whileStepping = createWhileSteppingAction(command.substring(TC_WHILE_STEPPING.length()));
					if (whileStepping != null) {
						subActions = new ArrayList<>();
					}
				} else if (command.equals(TC_END)) {
					if (whileStepping == null || subActions == null) {
						continue;
					}
					StringBuilder sb = new StringBuilder();
					boolean first = true;
					for (ITracepointAction a : subActions) {
						if (first) {
							first = false;
						} else {
							sb.append(',');
						}
						sb.append(a.getName());
					}
					whileStepping.setSubActionsNames(sb.toString());
					whileStepping.setSubActionsContent(sb.toString());
					action = whileStepping;
					// Search for existing action for this 'while-stepping' command
					for (ITracepointAction a : tam.getActions()) {
						if (whileStepping.getSummary().equals(a.getSummary())) {
							action = a;
							found = true;
							break;
						}
					}
					whileStepping = null;
					subActions.clear();
					subActions = null;
				}
				if (action != null) {
					if (!found) {
						TracepointActionManager.getInstance().addAction(action);
					}
					if (whileStepping == null || subActions == null) {
						list.add(action);
					} else {
						subActions.add(action);
					}
				}
			}
			TracepointActionManager.getInstance().saveActionData();
		}
		return list.toArray(new ITracepointAction[list.size()]);
	}

	private CollectAction createCollectAction(String collectStr) {
		CollectAction action = new CollectAction();
		action.setName(TracepointActionManager.getInstance().makeUniqueActionName(action.getDefaultName()));
		action.setCollectString(collectStr);
		return action;
	}

	private EvaluateAction createEvaluateAction(String evalStr) {
		EvaluateAction action = new EvaluateAction();
		action.setName(TracepointActionManager.getInstance().makeUniqueActionName(action.getDefaultName()));
		action.setEvalString(evalStr);
		return action;
	}

	private WhileSteppingAction createWhileSteppingAction(String str) {
		WhileSteppingAction action = new WhileSteppingAction();
		action.setName(TracepointActionManager.getInstance().makeUniqueActionName(action.getDefaultName()));
		try {
			action.setStepCount(Integer.parseInt(str.trim()));
		} catch (NumberFormatException e) {
			return null;
		}
		return action;
	}

	protected void getSource(IBreakpointsTargetDMContext bpTargetDMC, final String debuggerPath,
			final DataRequestMonitor<String> rm) {

		ISourceLookup sourceLookup = getServicesTracker().getService(ISourceLookup.class);
		if (sourceLookup == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Source lookup service is not available")); //$NON-NLS-1$
			rm.done();
			return;
		}

		ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(bpTargetDMC, ISourceLookupDMContext.class);
		if (srcDmc == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "No source lookup context")); //$NON-NLS-1$
			rm.done();
			return;
		}

		if (debuggerPath == null || debuggerPath.isEmpty()) {
			rm.done();
			return;
		}

		sourceLookup.getSource(srcDmc, debuggerPath, new DataRequestMonitor<>(getExecutor(), rm) {
			@Override
			@ConfinedToDsfExecutor("fExecutor")
			protected void handleCompleted() {
				String fileName = null;
				if (isSuccess()) {
					if (getData() instanceof IFile) {
						fileName = ((IFile) getData()).getLocation().toOSString();
					} else if (getData() instanceof File) {
						fileName = ((File) getData()).getAbsolutePath();
					} else if (getData() instanceof ITranslationUnit) {
						IPath location = ((ITranslationUnit) getData()).getLocation();
						if (location != null) {
							fileName = location.toOSString();
						}
					} else if (getData() instanceof LocalFileStorage) {
						fileName = ((LocalFileStorage) getData()).getFile().getAbsolutePath();
					}
				}
				rm.setData((fileName != null && !fileName.isEmpty()) ? fileName : debuggerPath);
				rm.done();
			}
		});
	}

	/**
	 * Return true if target breakpoint is a function breakpoint
	 * @param miBpt target breakpoint
	 * @return true if this is a function breakpoint
	 * @since 5.3
	 */
	protected boolean isFunctionBreakpoint(MIBreakpoint miBpt) {
		String origFunction = getFunctionFromOriginalLocation(miBpt.getOriginalLocation());
		if (miBpt.getFunction().isEmpty()) {
			return !origFunction.isEmpty();
		}
		String function = miBpt.getFunction();
		// For C++ the function name for "break x" is reported as "x()".
		// To compare it to the name retrieved from the original location
		// we need to remove "()".
		int index = function.indexOf('(');
		if (index > 0 && origFunction.indexOf('(') == -1) {
			return function.substring(0, index).equals(origFunction);
		}
		return function.equals(origFunction);
	}

	/**
	 * Return true if target breakpoint is an address breakpoint
	 * @param miBpt target breakpoint
	 * @return true if this is an address breakpoint
	 * @since 5.3
	 */
	protected boolean isAddressBreakpoint(MIBreakpoint miBpt) {
		return miBpt.getOriginalLocation().startsWith("*"); //$NON-NLS-1$
	}

	/**
	 * Return true if target breakpoint is a line breakpoint
	 * @param miBpt target breakpoint
	 * @return true if this is a line breakpoint
	 * @since 5.3
	 */
	protected boolean isLineBreakpoint(MIBreakpoint miBpt) {
		return !isFunctionBreakpoint(miBpt) && !isAddressBreakpoint(miBpt);
	}

	private IAddress getPlatformAddress(String miAddress) {
		int radix = 10;
		if (miAddress.startsWith("0x")) { //$NON-NLS-1$
			radix = 16;
			miAddress = miAddress.substring(2);
		}
		return new Addr64(new BigInteger(miAddress, radix));
	}

	private boolean isBreakpointTargetTracked(IBreakpointsTargetDMContext btTargetDMC) {
		return fTrackedTargets.contains(btTargetDMC);
	}

	/**
	 * Obtain the file name of the target breakpoint.
	 *
	 * @param miBpt target breakpoint
	 * @return file name
	 * @since 5.3
	 */
	protected String getFileName(MIBreakpoint miBpt) {
		String fileName = (miBpt.getFullName() != null && !miBpt.getFullName().isEmpty()) ? miBpt.getFullName()
				: miBpt.getFile();
		if (fileName != null && !fileName.isEmpty()) {
			return fileName;
		}
		// When a breakpoint is set from the console on an invalid file both
		// 'file' and 'fullname' attributes are not available, we need to parse
		// the 'original-location' attribute to retrieve the file name.
		String origLocation = miBpt.getOriginalLocation();
		if (origLocation.isEmpty()) {
			// Shouldn't happen
			GdbPlugin.log(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invalid 'original-location' attribute")); //$NON-NLS-1$
			return ""; //$NON-NLS-1$
		}
		if (origLocation.startsWith("*")) { //$NON-NLS-1$
			// Address breakpoint
			return ""; //$NON-NLS-1$
		}
		int index = origLocation.lastIndexOf(':');
		return (index > 0) ? origLocation.substring(0, index) : ""; //$NON-NLS-1$
	}

	/**
	 * Obtain the line number of the target breakpoint.
	 *
	 * @param miBpt target breakpoint
	 * @return line number
	 * @since 5.3
	 */
	protected int getLineNumber(MIBreakpoint miBpt) {
		int lineNumber = miBpt.getLine();
		if (lineNumber != -1) {
			return lineNumber;
		}
		// When a breakpoint is set from the console on an invalid file
		// the 'line' attributes is not available, we need to parse
		// the 'original-location' attribute to retrieve the line number.
		String origLocation = miBpt.getOriginalLocation();
		if (origLocation.isEmpty()) {
			// Shouldn't happen
			GdbPlugin.log(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invalid 'original-location' attribute")); //$NON-NLS-1$
			return -1;
		}
		if (origLocation.startsWith("*")) { //$NON-NLS-1$
			// Address breakpoint
			return -1;
		}
		int index = origLocation.lastIndexOf(':');
		if (index > 0 && origLocation.length() > index + 1) {
			try {
				return Integer.valueOf(origLocation.substring(index + 1, origLocation.length())).intValue();
			} catch (NumberFormatException e) {
				// not a line breakpoint
			}
		}
		return -1;
	}

	/**
	 * Obtain the function name of the target breakpoint.
	 *
	 * @param miBpt target breakpoint
	 * @return function name
	 * @since 5.3
	 */
	protected String getFunctionName(MIBreakpoint miBpt) {
		if (miBpt.getFunction() != null && !miBpt.getFunction().isEmpty())
			return miBpt.getFunction();
		// When a function breakpoint is set from the console, the symbol associated with
		// the function may not be known to GDB. In this case the 'function' attribute is
		// not available, we need to parse the 'original-location' attribute to retrieve
		// the function name.
		return getFunctionFromOriginalLocation(miBpt.getOriginalLocation());
	}

	private IResource getResource(String fileName) {
		IResource resource = null;
		if (fileName == null || fileName.isEmpty()) {
			resource = ResourcesPlugin.getWorkspace().getRoot();
		} else {
			IFile[] files = ResourcesPlugin.getWorkspace().getRoot()
					.findFilesForLocationURI(new File(fileName).toURI());
			if (files.length > 0) {
				resource = files[0];
			} else {
				resource = ResourcesPlugin.getWorkspace().getRoot();
			}
		}
		return resource;
	}

	@DsfServiceEventHandler
	public void eventDispatched(IExitedDMEvent e) {
		if (e.getDMContext() instanceof IBreakpointsTargetDMContext) {
			// Remove breakpoint entries when a breakpoint target is removed.
			// This will happen for GDB < 7.4 where the container is the breakpoint target.
			// For GDB >= 7.4, GDB is the breakpoint target and will not be removed.
			IBreakpointsTargetDMContext bpTargetDMContext = (IBreakpointsTargetDMContext) e.getDMContext();
			Map<String, MIBreakpoint> createdBreakpoints = fCreatedTargetBreakpoints.remove(bpTargetDMContext);
			if (createdBreakpoints != null) {
				createdBreakpoints.clear();
			}
			Map<String, MIBreakpoint> modifications = fPendingModifications.remove(bpTargetDMContext);
			if (modifications != null) {
				modifications.clear();
			}
			Set<String> deletedBreakpoints = fDeletedTargetBreakpoints.remove(bpTargetDMContext);
			if (deletedBreakpoints != null) {
				deletedBreakpoints.clear();
			}
		}
	}

	private String getFunctionFromOriginalLocation(String origLocation) {
		if (origLocation.isEmpty()) {
			// Shouldn't happen
			GdbPlugin.log(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invalid 'original-location' attribute")); //$NON-NLS-1$
			return ""; //$NON-NLS-1$
		}
		if (origLocation.startsWith("*")) { //$NON-NLS-1$
			// Address breakpoint
			return ""; //$NON-NLS-1$
		}
		int index = origLocation.lastIndexOf(':');
		String function = (index >= 0) ? origLocation.substring(index + 1) : origLocation;
		try {
			//TODO This does not work for dprintf since the output of the orginal location can look like this:
			//original-location="/home/lmckhou/runtime-TestDSF/Producer/src/Producer.cpp:100,\\"Hit line %d of /home/lmckhou/runtime-TestDSF/Producer/src/Producer.cpp\\\\n\\",100"
			Integer.valueOf(function);
			// Line breakpoint
			return ""; //$NON-NLS-1$
		} catch (NumberFormatException e) {
			// possible function breakpoint
		}
		return function;
	}

	protected boolean isCatchpoint(MIBreakpoint miBpt) {
		// Since we are using the CLI 'catch' command to set catchpoints GDB will emit
		// the 'breakpoint-created' notification even if the catchpoint is set from UI.
		// In case of 'catch' and 'throw' events the value of the 'type' attribute in
		// the breakpoint notification's data is 'breakpoint' instead of 'catchpoint'.
		// In this cases to identify the correct type we need to check the content of
		// the 'what' attribute.
		return (miBpt.isCatchpoint() || (!miBpt.isWatchpoint() && (CE_EXCEPTION_CATCH.equals(miBpt.getExpression())
				|| CE_EXCEPTION_THROW.equals(miBpt.getExpression()))));
	}

}
