/*******************************************************************************
 * Copyright (c) 2009, 2011 Nokia and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Nokia - Initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.debug.edc.internal.services.dsf;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.breakpointactions.BreakpointActionManager;
import org.eclipse.cdt.debug.core.breakpointactions.IBreakpointAction;
import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
import org.eclipse.cdt.debug.core.model.ICWatchpoint;
import org.eclipse.cdt.debug.core.model.ICWatchpoint2;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.EDCTrace;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.ModuleDMC;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.ModuleLoadedEvent;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.ModuleUnloadedEvent;
import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC;
import org.eclipse.cdt.debug.edc.launch.EDCLaunch;
import org.eclipse.cdt.debug.edc.services.AbstractEDCService;
import org.eclipse.cdt.debug.edc.services.DMContext;
import org.eclipse.cdt.debug.edc.services.IDSFServiceUsingTCF;
import org.eclipse.cdt.debug.edc.services.IEDCDMContext;
import org.eclipse.cdt.debug.edc.services.IEDCExpression;
import org.eclipse.cdt.debug.edc.services.ITargetEnvironment;
import org.eclipse.cdt.debug.edc.services.Stack;
import org.eclipse.cdt.debug.edc.tcf.extension.ProtocolConstants.IModuleProperty;
import org.eclipse.cdt.debug.internal.core.breakpoints.BreakpointProblems;
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Immutable;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress;
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator2;
import org.eclipse.cdt.dsf.debug.service.IBreakpointAttributeTranslator;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.cdt.dsf.debug.service.IModules.ModuleLoadedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IModules.ModuleUnloadedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.utils.Addr32;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.model.MemoryByte;
import org.eclipse.tm.tcf.protocol.IService;
import org.eclipse.tm.tcf.protocol.IToken;
import org.eclipse.tm.tcf.protocol.Protocol;
import org.eclipse.tm.tcf.services.IBreakpoints.DoneCommand;

public class Breakpoints extends AbstractEDCService implements IBreakpoints, IDSFServiceUsingTCF {

	/**
	 * Breakpoint attributes markers used in the map parameters of
	 * insert/updateBreakpoint(). All are optional with the possible exception
	 * of TYPE. It is the responsibility of the
	 * {@link IBreakpointAttributeTranslator} to ensure that the set of
	 * attributes provided is sufficient to create/update a valid breakpoint on
	 * the back-end.
	 */
	public static final String PREFIX = "org.eclipse.cdt.debug.edc.breakpoint"; //$NON-NLS-1$

	// Our own attribute keys.
	//
	/**
	 * Breakpoint type: value is string.
	 */
	public static final String BREAKPOINT_TYPE = PREFIX + ".type"; //$NON-NLS-1$
		// type values:
		public static final String BREAKPOINT = "breakpoint"; //$NON-NLS-1$
		public static final String WATCHPOINT = "watchpoint"; //$NON-NLS-1$
		public static final String CATCHPOINT = "catchpoint"; //$NON-NLS-1$

	/**
	 * breakponint sub-type: value is string.
	 */
	public static final String BREAKPOINT_SUBTYPE = PREFIX + ".subtype"; //$NON-NLS-1$
		// sub-type values:
		public static final String LINE_BREAKPOINT = "line_bp"; //$NON-NLS-1$
		public static final String FUNCTION_BREAKPOINT = "function_bp"; //$NON-NLS-1$
		public static final String ADDRESS_BREAKPOINT = "address_bp"; //$NON-NLS-1$

	/**
	 * breakpoint runtime address: value is hex string with no preceding "0x". 
	 */
	public static final String RUNTIME_ADDRESS = PREFIX + ".runtime_addr";

	/**
	 * TCF properties using keys from {@link org.eclipse.tm.tcf.services.IBreakpoints}
	 */
	public static final String TCF_PROPERTIES = PREFIX + ".tcf_properties"; //$NON-NLS-1$
	private static final String TCF_BP_ACCESSMODE	= org.eclipse.tm.tcf.services.IBreakpoints.PROP_ACCESSMODE;
//		private static final int TCF_BP_ACCESSMODE_CHANGE	= org.eclipse.tm.tcf.services.IBreakpoints.ACCESSMODE_CHANGE;
		private static final int TCF_BP_ACCESSMODE_EXECUTE	= org.eclipse.tm.tcf.services.IBreakpoints.ACCESSMODE_EXECUTE;
		private static final int TCF_BP_ACCESSMODE_READ		= org.eclipse.tm.tcf.services.IBreakpoints.ACCESSMODE_READ;
		private static final int TCF_BP_ACCESSMODE_WRITE	= org.eclipse.tm.tcf.services.IBreakpoints.ACCESSMODE_WRITE;
	private static final String TCF_BP_CONDITION	= org.eclipse.tm.tcf.services.IBreakpoints.PROP_CONDITION;
	private static final String TCF_BP_CONTEXTIDS	= org.eclipse.tm.tcf.services.IBreakpoints.PROP_CONTEXTIDS;
	private static final String TCF_BP_ENABLED		= org.eclipse.tm.tcf.services.IBreakpoints.PROP_ENABLED;
	private static final String TCF_BP_FILE			= org.eclipse.tm.tcf.services.IBreakpoints.PROP_FILE;
	private static final String TCF_BP_ID			= org.eclipse.tm.tcf.services.IBreakpoints.PROP_ID;
	private static final String TCF_BP_IGNORECOUNT	= org.eclipse.tm.tcf.services.IBreakpoints.PROP_IGNORECOUNT;
	private static final String TCF_BP_LINE			= org.eclipse.tm.tcf.services.IBreakpoints.PROP_LINE;
	private static final String TCF_BP_LOCATION		= org.eclipse.tm.tcf.services.IBreakpoints.PROP_LOCATION;
	private static final String TCF_BP_SIZE			= org.eclipse.tm.tcf.services.IBreakpoints.PROP_SIZE;
	private static final String TCF_BP_TYPE			= org.eclipse.tm.tcf.services.IBreakpoints.PROP_TYPE;
		private static final String TCF_BP_TYPE_AUTO	= org.eclipse.tm.tcf.services.IBreakpoints.TYPE_AUTO;

	// Error messages
	static final String NULL_STRING = ""; //$NON-NLS-1$
	static final String UNKNOWN_EXECUTION_CONTEXT = "Unknown execution context"; //$NON-NLS-1$
	static final String UNKNOWN_BREAKPOINT_CONTEXT = "Unknown breakpoint context"; //$NON-NLS-1$
	static final String UNKNOWN_BREAKPOINT_TYPE = "Unknown breakpoint type"; //$NON-NLS-1$
	static final String UNKNOWN_BREAKPOINT = "Unknown breakpoint"; //$NON-NLS-1$
	static final String BREAKPOINT_INSERTION_FAILURE = "Breakpoint insertion failure"; //$NON-NLS-1$
	static final String WATCHPOINT_INSERTION_FAILURE = "Watchpoint insertion failure"; //$NON-NLS-1$
	static final String INVALID_CONDITION = "Invalid condition"; //$NON-NLS-1$

	// User breakpoints (those from the IDE) currently installed.
	private final Map<IBreakpointDMContext, BreakpointDMData> userBreakpoints = new HashMap<IBreakpointDMContext, BreakpointDMData>();

	/**
	 * Internal temporary breakpoints set by debugger for stepping.
	 */
	private final List<BreakpointDMData> tempBreakpoints = new ArrayList<BreakpointDMData>();

	private org.eclipse.tm.tcf.services.IBreakpoints tcfBreakpointService;

	// Module in which startup breakpoint is installed for the debug session.
	private Map<ILaunchConfiguration, ModuleDMC> startupBreakpointModule = new HashMap<ILaunchConfiguration, ModuleDMC>();

	private ISourceLocator sourceLocator;

	/**
	 * Breakpoint problem markers added by EDC. Note these markers have life-span
	 * of a debug session, namely they are removed at end of a debug session or
	 * removed when corresponding breakpoint is removed by user.
	 * 
	 * Currently the markers are only used for breakpoint conditions, though it should
	 * be easy to extend the scope.....06/07/2011.
	 */
    private Map<IBreakpointDMContext, IMarker> fBreakpointMarkers = new HashMap<IBreakpointDMContext, IMarker>();

	static private long nextBreakpointID = 1;

	// /////////////////////////////////////////////////////////////////////////
	// Breakpoint Events
	// /////////////////////////////////////////////////////////////////////////

	public class BreakpointsChangedEvent extends AbstractDMEvent<IBreakpointsTargetDMContext> implements
			IBreakpointsChangedEvent {
		private IBreakpointDMContext[] eventBreakpoints;

		public BreakpointsChangedEvent(IBreakpointDMContext bp) {
			super(DMContexts.getAncestorOfType(bp, IBreakpointsTargetDMContext.class));
			eventBreakpoints = new IBreakpointDMContext[] { bp };
		}

		public IBreakpointDMContext[] getBreakpoints() {
			return eventBreakpoints;
		}
	}

	public class BreakpointAddedEvent extends BreakpointsChangedEvent implements IBreakpointsAddedEvent {
		public BreakpointAddedEvent(IBreakpointDMContext context) {
			super(context);
		}
	}

	public class BreakpointUpdatedEvent extends BreakpointsChangedEvent implements IBreakpointsUpdatedEvent {
		public BreakpointUpdatedEvent(IBreakpointDMContext context) {
			super(context);
		}
	}

	public class BreakpointRemovedEvent extends BreakpointsChangedEvent implements IBreakpointsRemovedEvent {
		public BreakpointRemovedEvent(IBreakpointDMContext context) {
			super(context);
		}
	}

	// /////////////////////////////////////////////////////////////////////////
	// IBreakpointDMContext
	// /////////////////////////////////////////////////////////////////////////
	@Immutable
	public static final class BreakpointDMContext extends DMContext implements IBreakpointDMContext {
		public BreakpointDMContext(String sessionID, IDMContext[] parents, long id) {
			super(sessionID, parents, Long.toString(id));
		}

		@Override
		public String toString() {
			return "BreakpointDMContext [id=" + getID() + "]";
		}
	}

	public class BreakpointDMData implements IBreakpointDMData {

		private final long id; // internal ID.
		private final IBreakpointDMContext context;
		private final IAddress[] addresses;
		private final byte[] originalInstruction;
		private Map<String, Object> properties;
		private int hitCount;

		public BreakpointDMData(long id, IBreakpointDMContext context, IAddress[] addresses,
				Map<String, Object> properties) {
			super();
			this.id = id;
			this.context = context;
			this.addresses = addresses;
			this.originalInstruction = null;
			this.properties = new HashMap<String, Object>(properties); // make a  copy
		}

		public BreakpointDMData(long id, IBreakpointDMContext context, IAddress[] addresses,
				byte[] fOriginalInstruction, Map<String, Object> properties) {
			super();
			this.id = id;
			this.context = context;
			this.addresses = addresses;
			this.originalInstruction = fOriginalInstruction;
			this.properties = new HashMap<String, Object>(properties);
		}

		public IAddress[] getAddresses() {
			return addresses;
		}

		public String getBreakpointType() {
			return (String) properties.get(BREAKPOINT_TYPE);
		}

		public String getCondition() {
			return (String) properties.get(ICBreakpoint.CONDITION);
		}

		public String getExpression() {
			return (String) properties.get(ICWatchpoint.EXPRESSION);
		}

		public String getFileName() {
			return (String) properties.get(ICBreakpoint.SOURCE_HANDLE);
		}

		public String getFunctionName() {
			return (String) properties.get(ICLineBreakpoint.FUNCTION);
		}

		public int getIgnoreCount() {
			Integer ic = (Integer) properties.get(ICBreakpoint.IGNORE_COUNT);
			if (ic == null)
				return 0;
			else
				return ic.intValue();
		}

		public int getLineNumber() {
			return (Integer) properties.get(IMarker.LINE_NUMBER);
		}

		public boolean isEnabled() {
			return (Boolean) properties.get(IBreakpoint.ENABLED);
		}

		public long getID() {
			return id;
		}

		public byte[] getOriginalInstruction() {
			return originalInstruction;
		}

		/**
		 * @return reference to properties map of the bp.
		 */
		public Map<String, Object> getProperties() {
			return properties;
		}

		public IBreakpointDMContext getContext() {
			return context;
		}

		@SuppressWarnings("unchecked")
		public Map<String, Object> getTCFProperties() {
			return (Map<String, Object>)properties.get(TCF_PROPERTIES);
		}

		public void setProperties(Map<String, Object> props) {
			properties = new HashMap<String, Object>(props);
		}

		public void setTCFProperties(Map<String, Object> tcfprops) {
			// insert a copy of the properties
			properties.put(TCF_PROPERTIES, new HashMap<String, Object>(tcfprops));
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + getOuterType().hashCode();
			result = prime * result + (int) (id ^ (id >>> 32));
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			BreakpointDMData other = (BreakpointDMData) obj;
			if (!getOuterType().equals(other.getOuterType()))
				return false;
			if (id != other.id)
				return false;
			return true;
		}

		private Breakpoints getOuterType() {
			return Breakpoints.this;
		}

		@Override
		public String toString() {
			String s = getFileName();
			if (s == null) // address breakpoint
				s = getAddresses()[0].toHexAddressString();
			else {
				if (getFunctionName() != null)
					s += ": " + getFunctionName();
				else
					s += ":line " + getLineNumber();
			}
			return "Breakpoint@" + s;
		}

		public void incrementHitCount() {
			hitCount++;
		}
		
		public int getHitCount() {
			return hitCount;
		}

		public boolean hasActions() {
			return properties.containsKey(BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE);
		}

		private void doExecuteActions(final RunControl.ExecutionDMC threadDMC, final RequestMonitorWithProgress rm) {
			assert getExecutor().isInExecutorThread();
			BreakpointsMediator2 bpm2 = getService(BreakpointsMediator2.class);
			final IBreakpoint ibp
			  = (bpm2 != null) ? bpm2.getPlatformBreakpoint(null, getContext()) : null;

			String actionProp = (String)properties.get(BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE);
			String[] actionNames = actionProp.split(",");
			for (int i = 0; i < actionNames.length; ++i) {
				final IBreakpointAction action
				  = CDebugCorePlugin.getDefault().getBreakpointActionManager().findBreakpointAction(actionNames[i]);
				if (action != null) {
					Runnable runnable = new Runnable() {
						public void run() {
							action.execute(ibp, threadDMC, rm.getProgressMonitor());
						}
					};
					asyncExec(runnable, rm);
				}
			}
		}

		public void executeActions(final RunControl.ExecutionDMC threadDMC, final RequestMonitorWithProgress rm) {
			if (!hasActions())
				return;

			if (getExecutor().isInExecutorThread()) {
				doExecuteActions(threadDMC, rm);
			} else {
				getExecutor().execute(new Runnable() {
					public void run() {
						doExecuteActions(threadDMC, rm);
					}
				});
			}
		}
	}

	public Breakpoints(DsfSession session) {
		super(session, new String[] { IBreakpoints.class.getName(), Breakpoints.class.getName() });
	}

	@Override
	public void initialize(final RequestMonitor rm) {
		super.initialize(new RequestMonitor(getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				// Register as event listener.
				getSession().addServiceEventListener(Breakpoints.this, null);
				rm.done();
			}
		});
	}

	public void getBreakpointDMData(IBreakpointDMContext dmc, DataRequestMonitor<IBreakpointDMData> drm) {
		if (!userBreakpoints.containsKey(dmc)) {
			drm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, UNKNOWN_BREAKPOINT));
		} else
			drm.setData(userBreakpoints.get(dmc));

		drm.done();
	}

	public void getBreakpoints(IBreakpointsTargetDMContext context, DataRequestMonitor<IBreakpointDMContext[]> drm) {
		Set<IBreakpointDMContext> breakpointIDs = userBreakpoints.keySet();
		drm.setData(breakpointIDs.toArray(new IBreakpointDMContext[breakpointIDs.size()]));
		drm.done();
	}

	/**
	 * Find breakpoint, either user-set or debugger internal temporary one, at
	 * the given address.
	 * 
	 * @param addr
	 *            - absolute runtime address.
	 * @return null if not found.
	 */
	public BreakpointDMData findBreakpoint(IAddress addr) {
		BreakpointDMData bp = findUserBreakpoint(addr);
		if (bp == null)
			bp = findTempBreakpoint(addr);
		return bp;
	}

	/**
	 * Find user breakpoint at the given address.
	 * 
	 * @param addr
	 *            - absolute runtime address.
	 * @return null if not found.
	 */
	public BreakpointDMData findUserBreakpoint(IAddress addr) {
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, "Find user breakpoint at " + addr.toHexAddressString()); }

		for (BreakpointDMData bp : userBreakpoints.values())
			if (bp.getAddresses()[0].equals(addr)) {
				if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(bp.toString())); }
				return bp;
			}

		if (EDCTrace.BREAKPOINTS_TRACE_ON) {EDCTrace.getTrace().traceExit(null, "not found.");}
		return null;
	}

	/**
	 * Find a temporary breakpoint at the given address.
	 * 
	 * @param addr
	 *            - absolute runtime address.
	 * @return null if not found.
	 */
	public BreakpointDMData findTempBreakpoint(IAddress addr) {
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, "Find temp breakpoint at " + addr.toHexAddressString()); }

		for (BreakpointDMData bp : tempBreakpoints) {
			if (bp.getAddresses()[0].equals(addr)) {
				if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(bp.toString())); }
				return bp;
			}
		}

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null, "not found."); }
		return null;
	}

	/**
	 * Remove software breakpoints inserted in memory by debugger from the given
	 * memory buffer starting from given address.
	 * 
	 * @param startAddr
	 *            start address of the memory data.
	 * @param memBuffer
	 *            a buffer containing data from memory. Its content will be
	 *            changed by this method if a breakpoint falls in the address
	 *            range.
	 */
	public void removeBreakpointFromMemoryBuffer(IAddress startAddr, MemoryByte[] memBuffer) {
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, "remove bp in memory area:" + startAddr.toHexAddressString() + "," + memBuffer.length); }

		// If the breakpoint is actually set by TCF agent, we have to assume
		// that the TCF agent would do this breakpoint removing for us as
		// we have no idea how the agent set the breakpoint (e.g. is it software
		// breakpoint ? if yes, what breakpoint instruction is used ?)
		//
		if (usesTCFBreakpointService())
			return;

		for (BreakpointDMData edcBp : userBreakpoints.values()) {
			// TODO: bail out if the bp is not software breakpoint.

			IAddress bpAddr = edcBp.getAddresses()[0];
			int bpOffset = (int) startAddr.distanceTo(bpAddr).longValue();
			if (bpOffset >= 0 && bpOffset < memBuffer.length) {
				// the breakpoint falls in the buffer. Restore the original
				// instruction.
				byte[] orgInst = edcBp.getOriginalInstruction();
				for (int i = 0; i < orgInst.length && i + bpOffset < memBuffer.length; i++) {
					memBuffer[bpOffset + i].setValue(orgInst[i]);
				}

				if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null, "breakpoint removed at offset " + bpOffset); }
			}
		}

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
	}

	public void insertBreakpoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes,
			DataRequestMonitor<IBreakpointDMContext> drm) {
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { attributes })); }

		// Validate the context
		if (context == null) {
			drm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, UNKNOWN_EXECUTION_CONTEXT,
					null));
			drm.done();
			return;
		}

		// Validate the breakpoint type
		String type = (String) attributes.get(BREAKPOINT_TYPE);
		if (type == null) {
			drm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, UNKNOWN_BREAKPOINT_TYPE,
					null));
			drm.done();
			return;
		}

		// And go...
		if (type.equals(BREAKPOINT)) {
			addBreakpoint(context, attributes, drm);
		} else if (type.equals(WATCHPOINT)) {
			addWatchpoint(context, attributes, drm);
		} else {
			drm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, UNKNOWN_BREAKPOINT_TYPE,
					null));
			drm.done();
		}

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
	}

	/**
	 * Set one target breakpoint.
	 * 
	 * @param context
	 * @param attributes
	 *            attributes for the target breakpoint. For EDC, it must contain
	 *            the RUNTIME_ADDRESS attribute.
	 * @param drm
	 */
	private void addBreakpoint(final IBreakpointsTargetDMContext context, final Map<String, Object> attributes,
			final DataRequestMonitor<IBreakpointDMContext> drm) {
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { attributes })); }

		IExecutionDMContext exe_dmc = DMContexts.getAncestorOfType(context, IExecutionDMContext.class);
		String bpAddr = (String)attributes.get(RUNTIME_ADDRESS);
		
		assert exe_dmc != null : "ExecutionDMContext is unknown in addBreakpoint().";
		assert bpAddr != null;
		
		createBreakpoint(exe_dmc, new Addr64(bpAddr, 16), attributes, new DataRequestMonitor<BreakpointDMData>(
				getExecutor(), drm) {

			@Override
			protected void handleSuccess() {
				final BreakpointDMData bpd = getData();

				enableBreakpoint(bpd, new RequestMonitor(getExecutor(), drm) {

					@Override
					protected void handleSuccess() {
						IBreakpointDMContext bp_dmc = bpd.getContext();
						drm.setData(bp_dmc);

						// Remember this in our global list.
						userBreakpoints.put(bp_dmc, bpd);

						drm.done();
					}
				});
			}
		});

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
	}

	/**
	 * Set one target watchpoint.
	 * 
	 * @param context
	 * @param attributes
	 *            attributes for the target breakpoint. For EDC, it must contain
	 *            the RUNTIME_ADDRESS attribute.
	 * @param drm
	 */
	private void addWatchpoint(final IBreakpointsTargetDMContext context, final Map<String, Object> attributes,
			final DataRequestMonitor<IBreakpointDMContext> drm) {
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { attributes })); }

		IExecutionDMContext exe_dmc = DMContexts.getAncestorOfType(context, IExecutionDMContext.class);
		String bpAddr = (String)attributes.get(RUNTIME_ADDRESS);

		assert exe_dmc != null : "DMContext is unknown in addWatchpoint().";
		assert bpAddr != null;
		
		createWatchpoint(exe_dmc, new Addr64(bpAddr, 16), attributes, new DataRequestMonitor<BreakpointDMData>(
				getExecutor(), drm) {

			@Override
			protected void handleSuccess() {
				final BreakpointDMData bpd = getData();

				enableBreakpoint(bpd, new RequestMonitor(getExecutor(), drm) {

					@Override
					protected void handleSuccess() {
						IBreakpointDMContext bp_dmc = bpd.getContext();
						drm.setData(bp_dmc);

						// Remember this in our global list.
						userBreakpoints.put(bp_dmc, bpd);

						drm.done();
					}
				});
			}
		});

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
	}

	public ISourceLocator getSourceLocator() {
		return sourceLocator;
	}

	public void setSourceLocator(ISourceLocator sourceLocator) {
		this.sourceLocator = sourceLocator;
	}

	/**
	 * Set temporary breakpoint at given address. This is for cases such as
	 * stepping and initial startup breakpoint (aka entry breakpoint).<br>
	 * If a user or temporary breakpoint already exists at the address, no
	 * temporary breakpoint will be set.
	 * 
	 * @param context
	 * @param address
	 * @param rm
	 */
	public void setTempBreakpoint(final IExecutionDMContext context, final IAddress address, final RequestMonitor rm) {

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, "set temp breakpoint at " + address.toHexAddressString()); }

		// If a breakpoint (user-set or temp) exists at the address, we are
		// done.
		if (findBreakpoint(address) != null) {
			rm.done();
			if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null, "A breakpoint exists at " + address.toHexAddressString()); }
			return;
		}

		createBreakpoint(context, address, new HashMap<String, Object>(), new DataRequestMonitor<BreakpointDMData>(
				getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				final BreakpointDMData bp_data = getData();

				enableBreakpoint(bp_data, new RequestMonitor(getExecutor(), rm) {
					@Override
					protected void handleSuccess() {
						// Remember this in our list.
						tempBreakpoints.add(bp_data);
						rm.done();

						if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg("A temp breakpoint successfully set at " + address.toHexAddressString())); }
					}
				});
			}
		});
	}

	/**
	 * Remove all temporary breakpoints set so far.
	 * 
	 * @param rm
	 */
	public void removeAllTempBreakpoints(final RequestMonitor rm) {

		int numTempBps = tempBreakpoints.size();
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, "remove " + numTempBps + " temp breakpoint" + ((numTempBps == 1)?"":"s") + "."); }

		if (numTempBps == 0) {
			rm.done();
			return;
		}

		CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm) {
			@Override
			protected void handleCompleted() {
				if (getStatus().isOK()) {
					tempBreakpoints.clear();
				}
				super.handleCompleted();
			}
		};

		crm.setDoneCount(tempBreakpoints.size());

		for (BreakpointDMData bp : tempBreakpoints)
			disableBreakpoint(bp, crm);
	}

	private void createBreakpoint(final IExecutionDMContext exeDMC,
			final IAddress address, final Map<String, Object> allProps,
			final DataRequestMonitor<BreakpointDMData> drm) {

		asyncExec(new Runnable() {
			public void run() {
				final long id = getNewBreakpointID();
				final IBreakpointDMContext bp_dmc
				  = new BreakpointDMContext(getSession().getId(),
						  					new IDMContext[] { exeDMC },
						  					id);
				final IAddress[] bp_addrs = new IAddress[] { address };

				if (usesTCFBreakpointService()) {
					final Map<String, Object> tcfProperties = new HashMap<String, Object>();

					tcfProperties.put(TCF_BP_ACCESSMODE, TCF_BP_ACCESSMODE_EXECUTE);
					tcfProperties.put(TCF_BP_ID, Long.toString(id));
					tcfProperties.put(TCF_BP_ENABLED, true);
					tcfProperties.put(TCF_BP_TYPE, TCF_BP_TYPE_AUTO);
					tcfProperties.put(TCF_BP_LOCATION, address.toString());
					tcfProperties.put(TCF_BP_CONTEXTIDS, getTcfContextIDs(exeDMC));

					ITargetEnvironment te = getTargetEnvironmentService();
					te.updateBreakpointProperties(exeDMC, address, tcfProperties);

					transferOptionalTcfProperties(allProps, tcfProperties);

					// save the separated TCF properties as a property
					// set amongst the regular properties; makes them
					// easy to pass as a set when calling the agent's add()
					allProps.put(TCF_PROPERTIES, tcfProperties);

					drm.setData(new BreakpointDMData(id, bp_dmc, bp_addrs, allProps));
					drm.done();
				} else { // generic software breakpoint
					final byte[] bpInstruction = getTargetEnvironmentService().getBreakpointInstruction(exeDMC, address);
					final int inst_size = bpInstruction.length;

					Memory memoryService = getService(Memory.class);
					IMemoryDMContext mem_dmc = DMContexts.getAncestorOfType(exeDMC, IMemoryDMContext.class);

					memoryService.getMemory(mem_dmc, address, 0, 1, inst_size, new DataRequestMonitor<MemoryByte[]>(
							getExecutor(), drm) {
						@Override
						protected void handleSuccess() {
							MemoryByte[] org_inst = getData();
							final byte[] org_inst_bytes = new byte[org_inst.length];
							for (int i = 0; i < org_inst.length; i++) {
								// make sure each byte is okay
								if (!org_inst[i].isReadable()) {
									drm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,
												("Cannot read memory at 0x" + address.add(i).getValue().toString(16)),
												null));
									drm.done();
									return;
								}
								org_inst_bytes[i] = org_inst[i].getValue();
							}

							drm.setData(new BreakpointDMData(id, bp_dmc, bp_addrs, org_inst_bytes, allProps));
							drm.done();
						}
					});
				}
			}
		}, drm);
	}

	private void createWatchpoint(final IDMContext dmc, final IAddress address,
			final Map<String, Object> allProps,
			final DataRequestMonitor<BreakpointDMData> drm) {
		asyncExec(new Runnable() {
			public void run() {
				final long id = getNewBreakpointID();
				final IBreakpointDMContext bp_dmc
				  = new BreakpointDMContext(getSession().getId(),
						  					new IDMContext[] { dmc },
						  					id);
				final IAddress[] bp_addrs = new IAddress[] { address };

				if (hasTCFWatchpointSupport()) {
					final Map<String, Object> tcfProperties = new HashMap<String, Object>();
					tcfProperties.put(TCF_BP_ID, Long.toString(id));
					tcfProperties.put(TCF_BP_ENABLED, true);
					tcfProperties.put(TCF_BP_TYPE, TCF_BP_TYPE_AUTO);
					tcfProperties.put(TCF_BP_LOCATION, address.toString());

					Boolean wpRead  = (Boolean)allProps.get(ICWatchpoint.READ);
					Boolean wpWrite = (Boolean)allProps.get(ICWatchpoint.WRITE);
					int accessMode
					  = ((wpRead != null && wpRead) ? TCF_BP_ACCESSMODE_READ : 0)
					  | ((wpWrite != null && wpWrite) ? TCF_BP_ACCESSMODE_WRITE : 0);
					tcfProperties.put(TCF_BP_ACCESSMODE, accessMode);

					Number wpSize = (Number)allProps.get(ICWatchpoint2.RANGE);
					if (wpSize != null)
						tcfProperties.put(TCF_BP_SIZE, wpSize);

					tcfProperties.put(TCF_BP_CONTEXTIDS, getTcfContextIDs(dmc));

					ITargetEnvironment te = getTargetEnvironmentService();
					te.updateBreakpointProperties(dmc, address, tcfProperties);

					transferOptionalTcfProperties(allProps, tcfProperties);

					allProps.put(TCF_PROPERTIES, tcfProperties);

					drm.setData(new BreakpointDMData(id, bp_dmc, bp_addrs, allProps));
				} else { // generic software watchpoint?  i don't think so, tim!
					drm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,
							"Watchpoints not supported for this system", null));
				}
				drm.done();
			}			
		}, drm);
	}


	/**
	 * Pass "contexts" for which the BP/WP is supposed to work.
	 * <br>
	 * Commonly utility used when creating breakpoint or watchpoint
	 * 
	 * @param dmc 
	 * @return String[] array representing contexts<br>
	 * NOTE: EDC extension to TCF:
	 *  TCF only define "IBreakpoints.PROP_CONTEXTIDS" as an array of IDs. 
	 *  In EDC, it's required the first element in the array be
	 *  IBreakpointsTargetDMContext which is usually (but not always) a
	 *  process. This makes EDC backward compatible with some existing TCF agents.
	 * 
	 */
	private String[] getTcfContextIDs(final IDMContext dmc) {
		// Pass "contexts" for which the BP is supposed to work.
		// NOTE: EDC extension to TCF: 
		IBreakpointsTargetDMContext bpTargetDMC
		  = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class);
		// pass "dmc" as a context if it's different from bpTargetDMC
		if (! dmc.equals(bpTargetDMC))
			return new String[] {((IEDCDMContext)bpTargetDMC).getID(),
							  ((IEDCDMContext)dmc).getID()};

		return new String[] {((IEDCDMContext)bpTargetDMC).getID()};
	}

	/**
	 * Looks for properties recognized by TCF and puts them in
	 * the propertie list that will passed to the agent.
	 * <br>
	 * Commonly utility used when creating breakpoint or watchpoint
	 * @param bpProps
	 * @param tcfProperties
	 */
	private void transferOptionalTcfProperties(
			final Map<String, Object> bpProps,
			final Map<String, Object> tcfProperties) {

		// the following are optional, and may not apply to all agents
		Object sourceHandle = bpProps.get(ICBreakpoint.SOURCE_HANDLE);
		if (sourceHandle instanceof String)
			tcfProperties.put(TCF_BP_FILE, sourceHandle);

		Object lineNumber = bpProps.get(ICBreakpoint.SOURCE_HANDLE);
		if (lineNumber instanceof Number)
			tcfProperties.put(TCF_BP_LINE, lineNumber);

		Object condition = bpProps.get(ICBreakpoint.CONDITION);
		if (condition instanceof String)
			tcfProperties.put(TCF_BP_CONDITION, condition);

		Object ignoreCount = bpProps.get(ICBreakpoint.IGNORE_COUNT);
		if (ignoreCount instanceof Number)
			tcfProperties.put(TCF_BP_IGNORECOUNT, ignoreCount);

		// ok, so the following does not strictly conform to the API.
		// however, it helps in logging & debugging, will aid debugging
		// watchpoints which have an expression but not a file or
		// line-number, and, in the end, will make my friend ed happy.
		Object bpMessage = bpProps.get(IMarker.MESSAGE);
		if (bpMessage instanceof String)
			tcfProperties.put(IMarker.MESSAGE, bpMessage);
	}

	/**
	 * Install the breakpoint in the target process.
	 * 
	 * @param bp
	 * @param rm
	 */
	public void enableBreakpoint(final BreakpointDMData bp, final RequestMonitor rm) {
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(bp)); }
		
		if (usesTCFBreakpointService()) {
			Protocol.invokeLater(new Runnable() {
				public void run() {
					tcfBreakpointService.add(bp.getTCFProperties(), new DoneCommand() {

						public void doneCommand(IToken token, Exception error) {
							if (error != null) {
								// Make sure "done()" is called for the rm.
								rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,
										"TCF agent fails to install " + bp + " because:\n"
												+ error.getLocalizedMessage(), error));
								rm.done();
							} else {
								getSession().dispatchEvent(new BreakpointAddedEvent(bp.getContext()),
										new Hashtable<String, Object>(bp.getProperties()));

								rm.done();
							}
						}
					});
				}
			});
		} else {
			IAddress bp_addr = bp.getAddresses()[0];
			IExecutionDMContext exe_dmc = DMContexts.getAncestorOfType(bp.getContext(), IExecutionDMContext.class);
			byte[] bpInstruction = getTargetEnvironmentService().getBreakpointInstruction(exe_dmc, bp_addr);

			Memory memoryService = getService(Memory.class);
			IMemoryDMContext mem_dmc = DMContexts.getAncestorOfType(bp.getContext(), IMemoryDMContext.class);

			memoryService.setMemory(mem_dmc, bp_addr, 0, 1, bpInstruction.length, bpInstruction, rm);
			getSession().dispatchEvent(new BreakpointAddedEvent(bp.getContext()),
					new Hashtable<String, Object>(bp.getProperties()));
		}

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
	}

	private synchronized long getNewBreakpointID() {
		return nextBreakpointID++;
	}

	public void removeBreakpoint(final IBreakpointDMContext dmc, RequestMonitor rm) {
		// Remove user breakpoint in the target. 
		// This is called when user remove a breakpoint or when debug session ends.
		//
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { dmc })); }

		if (!(dmc instanceof BreakpointDMContext)) {
			// not our breakpoint, should not happen
			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, "Unrecognized breakpoint context."));
			rm.done();
			return;
		}

		if (!userBreakpoints.containsKey(dmc)) {
			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, UNKNOWN_BREAKPOINT));
			rm.done();
			return;
		}

		disableBreakpoint(userBreakpoints.get(dmc), new RequestMonitor(getExecutor(), rm) {

			@Override
			protected void handleCompleted() {
				// Regardless of success or failure of removing the bp on target, we'll do following.
				//
				// If user removes a breakpoint in UI, the platform won't keep the BP in UI just because 
				// of failure in removing the bp on target. However, any error passed by the "rm" will
				// be displayed in Error Log view. 
			
				// Remove it from our record.
				userBreakpoints.remove(dmc);

				// Remove problem marker if any. 
				// Note this may be called when the debug session is shut down.
				removeBreakpointProblemMarker(dmc);
				
				super.handleCompleted();
			}
		});

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
	}

	/**
	 * Remove the breakpoint from the target process.
	 * 
	 * @param bp
	 * @param rm
	 */
	public void disableBreakpoint(final BreakpointDMData bp, final RequestMonitor rm) {
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { bp })); } 

		if (!usesTCFBreakpointService()) {
			final Memory memoryService = getService(Memory.class);
			IMemoryDMContext mem_dmc = DMContexts.getAncestorOfType(bp.getContext(), IMemoryDMContext.class);
			byte[] orgInst = bp.getOriginalInstruction();
			memoryService.setMemory(mem_dmc, bp.getAddresses()[0], 0, 1, orgInst.length, orgInst, rm);
		} else {
			Protocol.invokeLater(new Runnable() {
				public void run() {
					Map<String, Object> properties = bp.getTCFProperties();
					String id = (String) properties.get(org.eclipse.tm.tcf.services.IBreakpoints.PROP_ID);
					tcfBreakpointService.remove(new String[] { id }, new DoneCommand() {

						public void doneCommand(IToken token, Exception error) {
							rm.done();
						}
					});
				}
			});
		}

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
	}

	public void updateBreakpoint(IBreakpointDMContext dmc, Map<String, Object> delta, RequestMonitor rm) {
		/*
		 * For EDC, we don't need to do any update on non-significant attribute
		 * change, e.g. change of Install_count, ignore_count. For significant
		 * change, the breakpoint will just be re-installed. 
		 * See canUpdateAttributes().
		 */
		BreakpointDMData bp = userBreakpoints.get(dmc);
		if (bp == null)
			assert false : "Fail to find BreakpointDMData linked with the IBreakpointDMContext:" + dmc;
		else {
			Map<String, Object> existingProps = bp.getProperties();
			for (String key : delta.keySet())
				existingProps.put(key, delta.get(key));
		}
		rm.done();
	}

	public boolean usesTCFBreakpointService() {
		return tcfBreakpointService != null;
	}

	private boolean hasTCFWatchpointSupport() {
		return usesTCFBreakpointService(); // TODO && tcfBreakpointService.supportsWatchpoints
	}

	public void tcfServiceReady(IService service) {
		tcfBreakpointService = (org.eclipse.tm.tcf.services.IBreakpoints) service;
	}

	@DsfServiceEventHandler
	public void eventHandler_installBreakpointsForModule(ModuleLoadedDMEvent e) {
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { e })); }

		// A new module (including main exe) is loaded. Install breakpoints for
		// it.
		ModuleLoadedEvent event = (ModuleLoadedEvent) e;
		final IExecutionDMContext executionDMC = event.getExecutionDMC();
		final ModuleDMC module = (ModuleDMC) e.getLoadedModuleContext();
		BreakpointsMediator2 bm = getService(BreakpointsMediator2.class);
		if (bm == null) {
			EDCDebugger.getMessageLogger().logError("Fail to get BreakpointsMediator service to install breakpoints for loaded module "+module, null);
			assert false;
			return;
		}
		
		final boolean requireResume	= requireResume(module);
	
		IBreakpointsTargetDMContext bt_dmc = DMContexts.getAncestorOfType(module, IBreakpointsTargetDMContext.class);
		bm.startTrackingBreakpoints(bt_dmc, new RequestMonitor(getExecutor(), null) {

			@Override
			protected void handleCompleted() {
				if (!isSuccess()) {
					// do we want to display a dialog for user ?
					// No, as it's expected not all breakpoints can be resolved
					// in the module.

					// Form readable message and log it.
					IStatus status = getStatus();
					String msg = MessageFormat.format(
							"Failed to install some breakpoints in the module [{0}]. Errors: \n", module.getName());
					if (status.isMultiStatus()) {
						for (IStatus s : ((MultiStatus) status).getChildren())
							msg += s.getMessage() + "\n";
					} else
						msg += status.getMessage();

					if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null, msg); }
				}

				// We should do these regardless of whether installing
				// breakpoints succeeded or not.
				setStartupBreakpoint(module, new RequestMonitor(getExecutor(), null) {

					@Override
					protected void handleCompleted() {
						// do this regardless of status of installing entry
						// breakpoint
						// as it's expected the startup bp not resolvable in all
						// modules.
						//
						if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null, "resume process after module load event ..."); }
						if (requireResume)
							((ExecutionDMC) executionDMC).resume(new RequestMonitor(getExecutor(), null));
					}
				});
			}
		});

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
	}

	/**
	 * Check if resume is required after handling load/unload of the given module.
	 * 
	 * @param module
	 * @return
	 */
	private boolean requireResume(ModuleDMC module) {
		boolean requireResume = true;
		Object propvalue = module.getProperties().get(IModuleProperty.PROP_RESUME);
		if (propvalue != null)
			if (propvalue instanceof Boolean)
				requireResume = (Boolean) propvalue;

		return requireResume;
	}

	/**
	 * Set breakpoint at startup point specified by user.
	 * 
	 * @param module
	 * @param rm
	 */
	protected void setStartupBreakpoint(ModuleDMC module, RequestMonitor rm) {
		EDCLaunch launch = EDCLaunch.getLaunchForSession(getSession().getId());
		ILaunchConfiguration launchConfig = launch.getLaunchConfiguration();
		if (startupBreakpointModule.get(launchConfig) != null) {
			// already set in a module for this launch configuration, no need to try it for any other module
			rm.done();
			return;
		}

		String startupStopAt = launch.getStartupStopAtPoint();
		// Is this even requested by user ?
		if (startupStopAt == null) {
			rm.done();
			return;
		}

		// Ask target environment whether it wants us to try installing
		// startup breakpoint in the module.
		ITargetEnvironment te = getTargetEnvironmentService();
		if (! te.needStartupBreakpointInExecutable(module.getName())) {
			rm.done();
			return;
		}

		IAddress iaddr = null;
		long address = 0;

		// Check if the point is absolute runtime address.
		//
		try {
			// first check if it's decimal number
			address = Long.parseLong(startupStopAt);
		} catch (NumberFormatException e) {
			// then check if it's hex
			if (startupStopAt.toLowerCase().startsWith("0x")) {
				try {
					address = Long.parseLong(startupStopAt.substring(2), 16);
				} catch (IllegalFormatException e1) {
					// ignore
				}
			}
		}

		if (address != 0) {
			iaddr = new Addr32(address);
			
			// Assume it is a link-time address first.  Run-time addresses are not predictable across launches.
			IAddress runAddr = module.toRuntimeAddress(iaddr);
			if (module.containsAddress(runAddr)) {
				iaddr = runAddr;
			} else {
				// Try for a runtime address.
				if (!module.containsAddress(iaddr)) {
					// address not in the module, don't bother.
					// This is to ensure the address breakpoint is installed
					// after the container module is loaded. 
					iaddr = null;
				}
			}
		} else {
			// the point is a symbol
			Symbols symService = getService(Symbols.class);
			List<IAddress> addrs = symService.getFunctionAddress(module, startupStopAt);
			
			if (addrs.size() > 0)
				// just choose the first one
				iaddr = addrs.get(0);
		}

		if (iaddr == null) {
			EDCDebugger.getMessageLogger().logError(
					"Could not resolve startup breakpoint: "+ startupStopAt, null);
			rm.done();
		} else {
			// The breakpoint is resolved in the module.
			startupBreakpointModule.put(launchConfig, module);

			IExecutionDMContext exe_dmc = DMContexts.getAncestorOfType(module, IExecutionDMContext.class);
			setTempBreakpoint(exe_dmc, iaddr, rm);
		}
	}

	@DsfServiceEventHandler
	public void eventHandler_uninstallBreakpointsForModule(ModuleUnloadedDMEvent e) {
		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { e.getClass().getName(), e })); }

		// An existing module (including main exe) is unloaded. Uninstall
		// breakpoints for it.
		ModuleUnloadedEvent event = (ModuleUnloadedEvent) e;
		final ExecutionDMC executionDMC = (ExecutionDMC)event.getExecutionDMC();
		final ModuleDMC module = (ModuleDMC) e.getUnloadedModuleContext();

		/*
		 * If module containing startup break is unloaded, mark the startup
		 * break as gone so that we can reinstall it the next time the module is
		 * loaded again in the same debug session.
		 */
		if (startupBreakpointModule != null &&
			startupBreakpointModule.equals(module))
			startupBreakpointModule = null;
		
		final boolean requireResume	= requireResume(module);
		
		BreakpointsMediator2 bm = getService(BreakpointsMediator2.class);
		IBreakpointsTargetDMContext bt_dmc = DMContexts.getAncestorOfType(e.getUnloadedModuleContext(),
				IBreakpointsTargetDMContext.class);
		bm.stopTrackingBreakpoints(bt_dmc, new RequestMonitor(getExecutor(), null) {
			@Override
			protected void handleFailure() {
				// super will just log the error.
				super.handleFailure();
				if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null, "uninstalling breakpoints failed"); }
			}

			@Override
			protected void handleSuccess() {
				super.handleSuccess();
				if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null, "breakpoints uninstalled and resume process..."); }
				if (requireResume)
					executionDMC.resume(new RequestMonitor(getExecutor(), null));
			}
		});

		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
	}

	protected void addBreakpointProblemMarker(final IBreakpointDMContext targetBP,
			final String description, final int severity) {
		BreakpointsMediator2 bmService = getService(BreakpointsMediator2.class);
		if (bmService == null)
			return;
		
		final IBreakpoint breakpoint = bmService.getPlatformBreakpoint(null, targetBP);
		if (breakpoint == null)
			return;

        if (! (breakpoint instanceof ICLineBreakpoint))
        	return;

        new Job("Add Breakpoint Problem Marker") { //$NON-NLS-1$
            @Override
            protected IStatus run(IProgressMonitor monitor) {
            	// If we have already have a problem marker on this breakpoint
            	// we should remove it first.
                IMarker marker = fBreakpointMarkers.remove(targetBP);
                if (marker != null) {
                    try {
                        marker.delete();
                    } catch (CoreException e) {
                    }
            	}

                ICLineBreakpoint lineBreakpoint = (ICLineBreakpoint) breakpoint;
                try {
                    // Locate the workspace resource via the breakpoint marker
                    IMarker breakpoint_marker = lineBreakpoint.getMarker();
                    IResource resource = breakpoint_marker.getResource();

                    // Add a problem marker to the resource
                    IMarker problem_marker = resource.createMarker(BreakpointProblems.BREAKPOINT_PROBLEM_MARKER_ID);
                    int line_number = lineBreakpoint.getLineNumber();
                    problem_marker.setAttribute(IMarker.LOCATION,    String.valueOf(line_number));
                    problem_marker.setAttribute(IMarker.MESSAGE,     description);
                    problem_marker.setAttribute(IMarker.SEVERITY,    severity);
                    problem_marker.setAttribute(IMarker.LINE_NUMBER, line_number);

                    // And save the baby
                    fBreakpointMarkers.put(targetBP, problem_marker);
                } catch (CoreException e) {
                }
                
                return Status.OK_STATUS;
            }
        }.schedule();
	}
	
	/**
	 * Remove problem marker added for the given target breakpoint.
	 * Note this may be called when debug session is shutdown.
	 *  
	 * @param breakpoint
	 */
    protected void removeBreakpointProblemMarker(final IBreakpointDMContext breakpoint) {

        final IMarker marker = fBreakpointMarkers.remove(breakpoint);
        if (marker == null)
        	return;
        
        new Job("Remove Breakpoint Problem Marker") { //$NON-NLS-1$
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                try {
                    marker.delete();
                } catch (CoreException e) {
                }

                return Status.OK_STATUS;
            }
        }.schedule();
    }

	/**
	 * Evaluate condition of given breakpoint, if any.
	 * 
	 * @param context 
	 *			  execution context in which to evaluate the condition.
	 * @param bp
	 *            the breakpoint.
	 * @param drm
	 *            DataRequestMonitor that contains result indicating whether
	 *            to stop execution of debugged program. The result value is
	 *            true if <br>
	 *            1. the breakpoint has no condition, or <br>
	 *            2. the breakpoint condition is invalid in syntax, or <br>
	 *            3. the breakpoint condition cannot be resolved, or <br>
	 *            4. the breakpoint condition is true.<br>
	 *            Otherwise the result in the drm is false.
	 * 
	 */
	public void evaluateBreakpointCondition(IExecutionDMContext context, final BreakpointDMData bp, final DataRequestMonitor<Object> drm) {
		final String expr = bp.getCondition();
		if (expr == null || expr.length() == 0) {
			bp.incrementHitCount();
			drm.setData(bp.getHitCount() > bp.getIgnoreCount() ? bp : false);
			drm.done();
			return;
		}

		Stack stackService = getService(Stack.class);

		stackService.getTopFrame(context, new DataRequestMonitor<IFrameDMContext>(getExecutor(), drm) {

			@Override
			protected void handleCompleted() {
				if (!isSuccess()) { // fail to get frame, namely cannot
									// evaluate the condition
					bp.incrementHitCount();
					drm.setData(bp.getHitCount() > bp.getIgnoreCount() ? bp : false);
					drm.done();
				} else {
					Expressions exprService = getService(Expressions.class);
					IEDCExpression expression = (IEDCExpression) exprService.createExpression(getData(), expr);
					FormattedValueDMContext fvc = exprService.getFormattedValueContext(expression,
							IFormattedValues.NATURAL_FORMAT);
					FormattedValueDMData value = expression.getFormattedValue(fvc);
					/*
					 * honor the breakpoint if the condition is true or
					 * invalid.
					 */
					String vstr = value.getFormattedValue();
					if (! vstr.equals("true") && ! vstr.equals("false")) //$NON-NLS-1$ //$NON-NLS-2$
						addBreakpointProblemMarker(bp.getContext(), "Breakpoint condition failed to resolve to boolean: " + vstr, IMarker.SEVERITY_WARNING);
					else // remove any problem marker
						removeBreakpointProblemMarker(bp.getContext());
					
					if (!vstr.equals("false"))
					{
						bp.incrementHitCount();
						drm.setData(bp.getHitCount() > bp.getIgnoreCount() ? bp : false);
					}
					else
						drm.setData(false); //$NON-NLS-1$

					drm.done();
				}
			}
		});
	}
}
