/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.debug.core.breakpoints;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.model.Breakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.jdt.debug.core.IJavaBreakpoint;
import org.eclipse.jdt.debug.core.IJavaBreakpointListener;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.internal.debug.core.IJDIEventListener;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
import org.eclipse.jdt.internal.debug.core.model.JDIObjectValue;
import org.eclipse.jdt.internal.debug.core.model.JDIThread;
import org.eclipse.jdt.internal.debug.core.model.JDIType;

import com.ibm.icu.text.MessageFormat;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.event.ClassPrepareEvent;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.LocatableEvent;
import com.sun.jdi.event.ThreadStartEvent;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;

public abstract class JavaBreakpoint extends Breakpoint implements IJavaBreakpoint, IJDIEventListener, IDebugEventSetListener {

	/**
	 * Breakpoint attribute storing the expired value (value
	 * <code>"org.eclipse.jdt.debug.core.expired"</code>). This attribute is
	 * stored as a <code>boolean</code>. Once a hit count has been reached, a
	 * breakpoint is considered to be "expired".
	 */
	protected static final String EXPIRED = "org.eclipse.jdt.debug.core.expired"; //$NON-NLS-1$
	/**
	 * Breakpoint attribute storing a breakpoint's hit count value (value
	 * <code>"org.eclipse.jdt.debug.core.hitCount"</code>). This attribute is
	 * stored as an <code>int</code>.
	 */
	protected static final String HIT_COUNT = "org.eclipse.jdt.debug.core.hitCount"; //$NON-NLS-1$
	/**
	 * Breakpoint attribute storing the number of debug targets a breakpoint is
	 * installed in (value
	 * <code>"org.eclipse.jdt.debug.core.installCount"</code>). This attribute
	 * is a <code>int</code>.
	 */
	protected static final String INSTALL_COUNT = "org.eclipse.jdt.debug.core.installCount"; //$NON-NLS-1$

	/**
	 * Breakpoint attribute storing the fully qualified name of the type this
	 * breakpoint is located in. (value
	 * <code>"org.eclipse.jdt.debug.core.typeName"</code>). This attribute is a
	 * <code>String</code>.
	 */
	protected static final String TYPE_NAME = "org.eclipse.jdt.debug.core.typeName"; //$NON-NLS-1$

	/**
	 * Breakpoint attribute storing suspend policy code for this breakpoint.
	 * (value <code>"org.eclipse.jdt.debug.core.suspendPolicy</code>). This
	 * attribute is an <code>int</code> corresponding to
	 * <code>IJavaBreakpoint.SUSPEND_VM</code> or
	 * <code>IJavaBreakpoint.SUSPEND_THREAD</code>.
	 */
	protected static final String SUSPEND_POLICY = "org.eclipse.jdt.debug.core.suspendPolicy"; //$NON-NLS-1$

	/**
	 * Breakpoint attribute storing a comma delimited list of extension
	 * identifiers of breakpoint listeners. The listeners will be notified in
	 * the order specified in the list.
	 *
	 * @since 3.5
	 */
	public static final String BREAKPOINT_LISTENERS = JDIDebugPlugin.EXTENSION_POINT_JAVA_BREAKPOINT_LISTENERS;
	/**
	 * Breakpoint attribute storing the expired value of trigger point (value
	 * <code>"org.eclipse.jdt.debug.core.expiredTriggerPoint"</code>). This attribute is
	 * stored as a <code>boolean</code>. Once a trigger point is hit, a
	 * breakpoint is considered to be "expired" as trigger point for the session.
	 *
	 * @since 3.11
	 */
	public static final String EXPIRED_TRIGGER_POINT = "org.eclipse.jdt.debug.core.expiredTriggerPoint"; //$NON-NLS-1$

	/**
	 * Stores the collection of requests that this breakpoint has installed in
	 * debug targets. key: a debug target value: the requests this breakpoint
	 * has installed in that target
	 */
	protected HashMap<JDIDebugTarget, List<EventRequest>> fRequestsByTarget;

	/**
	 * The list of threads (ThreadReference objects) in which this breakpoint
	 * will suspend, associated with the target in which each thread exists
	 * (JDIDebugTarget). key: targets the debug targets (IJavaDebugTarget)
	 * value: thread the filtered thread (IJavaThread) in the given target
	 */
	protected Map<JDIDebugTarget, IJavaThread> fFilteredThreadsByTarget;

	/**
	 * Stores the type name that this breakpoint was last installed in. When a
	 * breakpoint is created, the TYPE_NAME attribute assigned to it is that of
	 * its top level enclosing type. When installed, the type may actually be an
	 * inner type. We need to keep track of the type type the breakpoint was
	 * installed in, in case we need to re-install the breakpoint for HCR (i.e.
	 * in case an inner type is HCR'd).
	 */
	protected String fInstalledTypeName = null;

	/**
	 * List of targets in which this breakpoint is installed. Used to prevent
	 * firing of more than one install notification when a breakpoint's requests
	 * are re-created.
	 */
	protected Set<IJavaDebugTarget> fInstalledTargets = null;

	/**
	 * List of active instance filters for this breakpoint (list of
	 * <code>IJavaObject</code>).
	 */
	protected List<IJavaObject> fInstanceFilters = null;

	/**
	 * List of breakpoint listener identifiers corresponding to breakpoint
	 * listener extensions. Listeners are cached with the breakpoint object such
	 * that they can be notified when a breakpoint is removed.
	 */
	private List<String> fBreakpointListenerIds = null;

	/**
	 * Empty instance filters array.
	 */
	protected static final IJavaObject[] fgEmptyInstanceFilters = new IJavaObject[0];

	/**
	 * Property identifier for a breakpoint object on an event request
	 */
	public static final String JAVA_BREAKPOINT_PROPERTY = "org.eclipse.jdt.debug.breakpoint"; //$NON-NLS-1$

	/**
	 * JavaBreakpoint attributes
	 */
	protected static final String[] fgExpiredEnabledAttributes = new String[] {
			EXPIRED, ENABLED };

	public JavaBreakpoint() {
		fRequestsByTarget = new HashMap<>(1);
		fFilteredThreadsByTarget = new HashMap<>(1);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.IBreakpoint#getModelIdentifier()
	 */
	@Override
	public String getModelIdentifier() {
		return JDIDebugModel.getPluginIdentifier();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.debug.core.model.Breakpoint#setMarker(org.eclipse.core.resources
	 * .IMarker)
	 */
	@Override
	public void setMarker(IMarker marker) throws CoreException {
		super.setMarker(marker);
		configureAtStartup();
	}

	/**
	 * Add this breakpoint to the breakpoint manager, or sets it as
	 * unregistered.
	 */
	protected void register(boolean register) throws CoreException {
		DebugPlugin plugin = DebugPlugin.getDefault();
		if (plugin != null && register) {
			plugin.getBreakpointManager().addBreakpoint(this);
		} else {
			setRegistered(false);
		}
	}

	/**
	 * Add the given event request to the given debug target. If the request is
	 * the breakpoint request associated with this breakpoint, increment the
	 * install count.
	 */
	protected void registerRequest(EventRequest request, JDIDebugTarget target)
			throws CoreException {
		if (request == null) {
			return;
		}
		List<EventRequest> reqs = getRequests(target);
		if (reqs.isEmpty()) {
			fRequestsByTarget.put(target, reqs);
		}
		reqs.add(request);
		target.addJDIEventListener(this, request);
		// update the install attribute on the breakpoint
		if (!(request instanceof ClassPrepareRequest)) {
			incrementInstallCount();
			// notification
			fireInstalled(target);
		}
	}

	/**
	 * Returns a String corresponding to the reference type name to the top
	 * enclosing type in which this breakpoint is located or <code>null</code>
	 * if no reference type could be found.
	 */
	protected String getEnclosingReferenceTypeName() throws CoreException {
		String name = getTypeName();
		if (name != null) {
			int index = name.indexOf('$');
			if (index == -1) {
				return name;
			}
			return name.substring(0, index);
		}
		return null;
	}

	/**
	 * Returns the requests that this breakpoint has installed in the given
	 * target.
	 */
	protected ArrayList<EventRequest> getRequests(JDIDebugTarget target) {
		ArrayList<EventRequest> list = (ArrayList<EventRequest>) fRequestsByTarget.get(target);
		if (list == null) {
			list = new ArrayList<>(2);
		}
		return list;
	}

	/**
	 * Remove the given request from the given target. If the request is the
	 * breakpoint request associated with this breakpoint, decrement the install
	 * count.
	 */
	protected void deregisterRequest(EventRequest request, JDIDebugTarget target)
			throws CoreException {
		target.removeJDIEventListener(this, request);
		// A request may be getting de-registered because the breakpoint has
		// been deleted. It may be that this occurred because of a marker
		// deletion.
		// Don't try updating the marker (decrementing the install count) if
		// it no longer exists.
		if (!(request instanceof ClassPrepareRequest) && getMarker().exists()) {
			decrementInstallCount();
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.internal.debug.core.IJDIEventListener#handleEvent(com
	 * .sun.jdi.event.Event,
	 * org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget)
	 */
	@Override
	public boolean handleEvent(Event event, JDIDebugTarget target,
			boolean suspendVote, EventSet eventSet) {
		if (event instanceof ClassPrepareEvent) {
			return handleClassPrepareEvent((ClassPrepareEvent) event, target,
					suspendVote);
		}
		ThreadReference threadRef = ((LocatableEvent) event).thread();
		JDIThread thread = target.findThread(threadRef);
		if (thread == null) {
			// wait for any thread start event sets to complete processing
			// see bug 271700
			try {
				Job.getJobManager().join(ThreadStartEvent.class, null);
			} catch (OperationCanceledException e) {
			} catch (InterruptedException e) {
			}
			thread = target.findThread(threadRef);
		}
		if (thread == null || thread.isIgnoringBreakpoints()) {
			return true;
		}
		return handleBreakpointEvent(event, thread, suspendVote);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.internal.debug.core.IJDIEventListener#eventSetComplete
	 * (com.sun.jdi.event.Event,
	 * org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget, boolean)
	 */
	@Override
	public void eventSetComplete(Event event, JDIDebugTarget target,
			boolean suspend, EventSet eventSet) {
		ThreadReference threadRef = null;
		if (event instanceof ClassPrepareEvent) {
			threadRef = ((ClassPrepareEvent) event).thread();
		} else if (event instanceof LocatableEvent) {
			threadRef = ((LocatableEvent) event).thread();
		}
		if (threadRef == null) {
			return;
		}
		JDIThread thread = target.findThread(threadRef);
		if (thread == null || thread.isIgnoringBreakpoints()) {
			return;
		}
		if (event instanceof ClassPrepareEvent) {
			classPrepareComplete(event, thread, suspend, eventSet);
		} else {
			thread.completeBreakpointHandling(this, suspend, true, eventSet);
		}
	}

	/**
	 * Call-back that the class prepare event has completed
	 * @param event the event
	 * @param thread the thread that sent the event
	 * @param suspend if the the thread was suspended
	 * @param eventSet the event set context
	 */
	protected void classPrepareComplete(Event event, JDIThread thread, boolean suspend, EventSet eventSet) {
		// resume the thread if this is a class load event to install a deferred
		// breakpoint (and the vote is to resume)
		if (thread != null && !suspend) {
			thread.resumedFromClassPrepare();
		}
	}

	/**
	 * Handle the given class prepare event, which was generated by the class
	 * prepare event installed in the given target by this breakpoint.
	 *
	 * If the class which has been loaded is a class in which this breakpoint
	 * should install, create a breakpoint request for that class.
	 * @param event the event
	 * @param target the target
	 * @param suspendVote the current suspend vote
	 * @return is the thread should suspend or not
	 */
	public boolean handleClassPrepareEvent(ClassPrepareEvent event, JDIDebugTarget target, boolean suspendVote) {
		try {
			if (!installableReferenceType(event.referenceType(), target)) {
				// Don't install this breakpoint in an
				// inappropriate type
				return true;
			}
			createRequest(target, event.referenceType());
		} catch (CoreException e) {
			JDIDebugPlugin.log(e);
		}
		return true;
	}

	/**
	 * @see IJDIEventListener#handleEvent(Event, JDIDebugTarget)
	 *
	 *      Handle the given event, which was generated by the breakpoint
	 *      request installed in the given target by this breakpoint.
	 */
	public boolean handleBreakpointEvent(Event event, JDIThread thread,
			boolean suspendVote) {
		expireHitCount(event);
		disableTriggerPoint(event);
		return !suspend(thread, suspendVote); // Resume if suspend fails
	}

	/**
	 * Delegates to the given thread to suspend, and returns whether the thread
	 * suspended It is possible that the thread will not suspend as directed by
	 * a Java breakpoint listener.
	 *
	 * @see IJavaBreakpointListener#breakpointHit(IJavaThread, IJavaBreakpoint)
	 */
	protected boolean suspend(JDIThread thread, boolean suspendVote) {
		return thread.handleSuspendForBreakpoint(this, suspendVote);
	}

	/**
	 * Returns whether the given reference type is appropriate for this
	 * breakpoint to be installed in the given target. Query registered
	 * breakpoint listeners.
	 */
	protected boolean installableReferenceType(ReferenceType type,
			JDIDebugTarget target) throws CoreException {
		String installableType = getTypeName();
		if (installableType == null )
			return false;
		String queriedType = type.name();
		if( queriedType == null) {
			return false;
		}
		int index = queriedType.indexOf('<');
		if (index != -1) {
			queriedType = queriedType.substring(0, index);
		}
		if (installableType.equals(queriedType)) {
			return queryInstallListeners(target, type);
		}
		index = queriedType.indexOf('$', 0);
		if (index == -1) {
			return false;
		}
		if (installableType.regionMatches(0, queriedType, 0, index)) {
			return queryInstallListeners(target, type);
		}
		return false;
	}

	/**
	 * Called when a breakpoint event is encountered. Expires the hit count in
	 * the event's request and updates the marker.
	 *
	 * @param event
	 *            the event whose request should have its hit count expired or
	 *            <code>null</code> to only update the breakpoint marker.
	 */
	protected void expireHitCount(Event event) {
		Integer requestCount = null;
		EventRequest request = null;
		if (event != null) {
			request = event.request();
			requestCount = (Integer) request.getProperty(HIT_COUNT);
		}
		if (requestCount != null) {
			if (request != null) {
				request.putProperty(EXPIRED, Boolean.TRUE);
			}
			try {
				setAttributes(fgExpiredEnabledAttributes, new Object[] {
						Boolean.TRUE, Boolean.FALSE });
				// make a note that we auto-disabled this breakpoint.
			} catch (CoreException ce) {
				JDIDebugPlugin.log(ce);
			}
		}
	}

	protected void disableTriggerPoint(Event event) {
		try{
			if (isTriggerPoint() && isEnabled()) {
					DebugPlugin.getDefault().getBreakpointManager().enableTriggerPoints(null, false);
					// make a note that we auto-disabled the trigger point for this breakpoint.
					// we re enable it at cleanup of JDITarget
				}
			}catch (CoreException ce) {
				JDIDebugPlugin.log(ce);
			}

	}

	/**
	 * Returns whether this breakpoint should be "skipped". Breakpoints are
	 * skipped if the breakpoint manager is disabled and the breakpoint is
	 * registered with the manager
	 *
	 * @return whether this breakpoint should be skipped
	 */
	public boolean shouldSkipBreakpoint() throws CoreException {
		DebugPlugin plugin = DebugPlugin.getDefault();
		return plugin != null && isRegistered()
				&& !plugin.getBreakpointManager().isEnabled();
	}

	/**
	 * Attempts to create a breakpoint request for this breakpoint in the given
	 * reference type in the given target.
	 *
	 * @return Whether a request was created
	 */
	protected boolean createRequest(JDIDebugTarget target, ReferenceType type)
			throws CoreException {
		if (shouldSkipBreakpoint()) {
			return false;
		}
		EventRequest[] requests = newRequests(target, type);
		if (requests == null) {
			return false;
		}
		fInstalledTypeName = type.name();
		for (EventRequest request : requests) {
			registerRequest(request, target);
		}
		return true;
	}

	/**
	 * Configure a breakpoint request with common properties:
	 * <ul>
	 * <li><code>JAVA_BREAKPOINT_PROPERTY</code></li>
	 * <li><code>HIT_COUNT</code></li>
	 * <li><code>EXPIRED</code></li>
	 * </ul>
	 * and sets the suspend policy of the request to suspend the event thread.
	 */
	protected void configureRequest(EventRequest request, JDIDebugTarget target)
			throws CoreException {
		request.setSuspendPolicy(getJDISuspendPolicy());
		request.putProperty(JAVA_BREAKPOINT_PROPERTY, this);
		configureRequestThreadFilter(request, target);
		configureRequestHitCount(request);
		configureInstanceFilters(request, target);
		// Important: only enable a request after it has been configured
		updateEnabledState(request, target);
	}

	/**
	 * Adds an instance filter to the given request. Since the implementation is
	 * request specific, subclasses must override.
	 *
	 * @param request
	 * @param object
	 *            instance filter
	 */
	protected abstract void addInstanceFilter(EventRequest request,
			ObjectReference object);

	/**
	 * Configure the thread filter property of the given request.
	 */
	protected void configureRequestThreadFilter(EventRequest request,
			JDIDebugTarget target) {
		IJavaThread thread = fFilteredThreadsByTarget.get(target);
		if (thread == null || (!(thread instanceof JDIThread))) {
			return;
		}
		setRequestThreadFilter(request,
				((JDIThread) thread).getUnderlyingThread());
	}

	/**
	 * Configure the given request's hit count
	 */
	protected void configureRequestHitCount(EventRequest request)
			throws CoreException {
		int hitCount = getHitCount();
		if (hitCount > 0) {
			request.addCountFilter(hitCount);
			request.putProperty(HIT_COUNT, new Integer(hitCount));
		}
	}

	protected void configureInstanceFilters(EventRequest request,
			JDIDebugTarget target) {
		if (fInstanceFilters != null && !fInstanceFilters.isEmpty()) {
			Iterator<IJavaObject> iter = fInstanceFilters.iterator();
			while (iter.hasNext()) {
				IJavaObject object = iter.next();
				if (object.getDebugTarget().equals(target)) {
					addInstanceFilter(request,
							((JDIObjectValue) object).getUnderlyingObject());
				}
			}
		}
	}

	/**
	 * Creates, installs, and returns all event requests for this breakpoint in
	 * the given reference type and and target.
	 *
	 * @return the event requests created or <code>null</code> if creation
	 *         failed
	 */
	protected abstract EventRequest[] newRequests(JDIDebugTarget target,
			ReferenceType type) throws CoreException;

	/**
	 * Add this breakpoint to the given target. After it has been added to the
	 * given target, this breakpoint will suspend execution of that target as
	 * appropriate.
	 */
	public void addToTarget(JDIDebugTarget target) throws CoreException {
		fireAdding(target);
		createRequests(target);
	}

	/**
	 * Creates event requests for the given target
	 */
	protected void createRequests(JDIDebugTarget target) throws CoreException {
		if (target.isTerminated() || shouldSkipBreakpoint()) {
			return;
		}
		String referenceTypeName = getTypeName();
		String enclosingTypeName = getEnclosingReferenceTypeName();
		if (referenceTypeName == null || enclosingTypeName == null) {
			return;
		}
		// create request to listen to class loads
		if (referenceTypeName.indexOf('$') == -1) {
			registerRequest(
					target.createClassPrepareRequest(enclosingTypeName), target);
			// register to ensure we hear about local and anonymous inner
			// classes
			registerRequest(
					target.createClassPrepareRequest(enclosingTypeName + "$*"), target); //$NON-NLS-1$
		} else {
			registerRequest(
					target.createClassPrepareRequest(referenceTypeName), target);
			// register to ensure we hear about local and anonymous inner
			// classes
			registerRequest(target.createClassPrepareRequest(enclosingTypeName
					+ "$*", referenceTypeName), target); //$NON-NLS-1$
		}

		// create breakpoint requests for each class currently loaded
		List<ReferenceType> classes = target.jdiClassesByName(referenceTypeName);
		if (classes.isEmpty() && enclosingTypeName.equals(referenceTypeName)) {
			return;
		}

		boolean success = false;
		Iterator<ReferenceType> iter = classes.iterator();
		while (iter.hasNext()) {
			ReferenceType type = iter.next();
			if (createRequest(target, type)) {
				success = true;
			}
		}

		if (!success) {
			addToTargetForLocalType(target, enclosingTypeName);
		}
	}

	/**
	 * Local types (types defined in methods) are handled specially due to the
	 * different types that the local type is associated with as well as the
	 * performance problems of using ReferenceType#nestedTypes. From the Java
	 * model perspective a local type is defined within a method of a type.
	 * Therefore the type of a breakpoint placed in a local type is the type
	 * that encloses the method where the local type was defined. The local type
	 * is enclosed within the top level type according to the VM. So if "normal"
	 * attempts to create a request when a breakpoint is being added to a target
	 * fail, we must be dealing with a local type and therefore resort to
	 * looking up all of the nested types of the top level enclosing type.
	 *
	 * @param target the target
	 * @param enclosingTypeName the type name of the enclosing type
	 * @throws CoreException if something bad happens
	 */
	protected void addToTargetForLocalType(JDIDebugTarget target, String enclosingTypeName) throws CoreException {
		List<ReferenceType> classes = target.jdiClassesByName(enclosingTypeName);
		for(ReferenceType type : classes) {
			for(ReferenceType nestedType : type.nestedTypes()) {
				if (createRequest(target, nestedType)) {
					break;
				}
			}
		}
	}

	/**
	 * Returns the JDI suspend policy that corresponds to this breakpoint's
	 * suspend policy
	 *
	 * @return the JDI suspend policy that corresponds to this breakpoint's
	 *         suspend policy
	 * @exception CoreException
	 *                if unable to access this breakpoint's suspend policy
	 *                setting
	 */
	protected int getJDISuspendPolicy() throws CoreException {
		int breakpointPolicy = getSuspendPolicy();
		if (breakpointPolicy == IJavaBreakpoint.SUSPEND_THREAD) {
			return EventRequest.SUSPEND_EVENT_THREAD;
		}
		return EventRequest.SUSPEND_ALL;
	}

	/**
	 * returns the default suspend policy based on the pref setting on the
	 * Java-Debug pref page
	 *
	 * @return the default suspend policy
	 * @since 3.2
	 */
	protected int getDefaultSuspendPolicy() {
		return Platform.getPreferencesService().getInt(
				JDIDebugPlugin.getUniqueIdentifier(),
				JDIDebugPlugin.PREF_DEFAULT_BREAKPOINT_SUSPEND_POLICY,
				IJavaBreakpoint.SUSPEND_THREAD,
				null);
	}

	/**
	 * Returns whether the hitCount of this breakpoint is equal to the hitCount
	 * of the associated request.
	 */
	protected boolean hasHitCountChanged(EventRequest request)
			throws CoreException {
		int hitCount = getHitCount();
		Integer requestCount = (Integer) request.getProperty(HIT_COUNT);
		int oldCount = -1;
		if (requestCount != null) {
			oldCount = requestCount.intValue();
		}
		return hitCount != oldCount;
	}

	/**
	 * Removes this breakpoint from the given target.
	 */
	public void removeFromTarget(final JDIDebugTarget target)
			throws CoreException {
		removeRequests(target);
		Object removed = fFilteredThreadsByTarget.remove(target);
		boolean changed = removed != null;
		boolean markerExists = markerExists();
		if (!markerExists || (markerExists && getInstallCount() == 0)) {
			fInstalledTypeName = null;
		}

		// remove instance filters
		if (fInstanceFilters != null && !fInstanceFilters.isEmpty()) {
			for (int i = 0; i < fInstanceFilters.size(); i++) {
				IJavaObject object = fInstanceFilters.get(i);
				if (object.getDebugTarget().equals(target)) {
					fInstanceFilters.remove(i);
					changed = true;
				}
			}
		}

		// fire change notification if required
		if (changed) {
			fireChanged();
		}

		// notification
		fireRemoved(target);
	}

	/**
	 * Remove all requests that this breakpoint has installed in the given debug
	 * target.
	 */
	protected void removeRequests(final JDIDebugTarget target) throws CoreException {
		// removing was previously done is a workspace runnable, but that is
		// not possible since it can be a resource callback (marker deletion)
		// that causes a breakpoint to be removed
		ArrayList<EventRequest> requests = new ArrayList<>(getRequests(target));
		// Iterate over a copy of the requests since this list of requests
		// can be changed in other threads which would cause an
		// ConcurrentModificationException
		Iterator<EventRequest> iter = requests.iterator();
		EventRequest req;
		while (iter.hasNext()) {
			req = iter.next();
			try {
				if (target.isAvailable() && !isExpired(req)) {
					EventRequestManager manager = target
							.getEventRequestManager();
					if (manager != null) {
						manager.deleteEventRequest(req); // disable & remove
					}
				}
			} catch (VMDisconnectedException e) {
				if (target.isAvailable()) {
					JDIDebugPlugin.log(e);
				}
			} catch (RuntimeException e) {
				target.internalError(e);
			} finally {
				deregisterRequest(req, target);
			}
		}
		fRequestsByTarget.remove(target);
	}

	/**
	 * Update the enabled state of the given request in the given target, which
	 * is associated with this breakpoint. Set the enabled state of the request
	 * to the enabled state of this breakpoint.
	 */
	protected void updateEnabledState(EventRequest request,
			JDIDebugTarget target) throws CoreException {
		internalUpdateEnabledState(request, isEnabled(), target);
	}

	/**
	 * Set the enabled state of the given request to the given value, also
	 * taking into account instance filters.
	 */
	protected void internalUpdateEnabledState(EventRequest request,
			boolean enabled, JDIDebugTarget target) {
		if (request.isEnabled() != enabled) {
			// change the enabled state
			try {
				// if the request has expired, do not disable.
				// BreakpointRequests that have expired cannot be deleted.
				if (!isExpired(request)) {
					request.setEnabled(enabled);
				}
			} catch (VMDisconnectedException e) {
			} catch (RuntimeException e) {
				target.internalError(e);
			}
		}
	}

	/**
	 * Returns whether this breakpoint has expired.
	 */
	public boolean isExpired() throws CoreException {
		return ensureMarker().getAttribute(EXPIRED, false);
	}

	/**
	 * Returns whether the given request is expired
	 */
	protected boolean isExpired(EventRequest request) {
		Boolean requestExpired = (Boolean) request.getProperty(EXPIRED);
		if (requestExpired == null) {
			return false;
		}
		return requestExpired.booleanValue();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#isInstalled()
	 */
	@Override
	public boolean isInstalled() throws CoreException {
		return ensureMarker().getAttribute(INSTALL_COUNT, 0) > 0;
	}

	/**
	 * Increments the install count of this breakpoint
	 */
	protected void incrementInstallCount() throws CoreException {
		int count = getInstallCount();
		setAttribute(INSTALL_COUNT, count + 1);
	}

	/**
	 * Returns the <code>INSTALL_COUNT</code> attribute of this breakpoint or 0
	 * if the attribute is not set.
	 */
	public int getInstallCount() throws CoreException {
		return ensureMarker().getAttribute(INSTALL_COUNT, 0);
	}

	/**
	 * Returns whether this trigger breakpoint has expired.
	 */
	public boolean isTriggerPointExpired() throws CoreException {
		return ensureMarker().getAttribute(EXPIRED_TRIGGER_POINT, false);
	}

	/**
	 * Decrements the install count of this breakpoint.
	 */
	protected void decrementInstallCount() throws CoreException {
		int count = getInstallCount();
		if (count > 0) {
			setAttribute(INSTALL_COUNT, count - 1);
		}
		if (count == 1) {
			if (isExpired()) {
				// if breakpoint was auto-disabled, re-enable it
				setAttributes(fgExpiredEnabledAttributes, new Object[] {
						Boolean.FALSE, Boolean.TRUE });
			}
		}
	}

	/**
	 * Sets the type name in which to install this breakpoint.
	 */
	protected void setTypeName(String typeName) throws CoreException {
		setAttribute(TYPE_NAME, typeName);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getTypeName()
	 */
	@Override
	public String getTypeName() throws CoreException {
		if (fInstalledTypeName == null) {
			return ensureMarker().getAttribute(TYPE_NAME, null);
		}
		return fInstalledTypeName;
	}

	/**
	 * Resets the install count attribute on this breakpoint's marker to "0".
	 * Resets the expired attribute on all breakpoint markers to
	 * <code>false</code>. Resets the enabled attribute on the breakpoint marker
	 * to <code>true</code>. If a workbench crashes, the attributes could have
	 * been persisted in an incorrect state.
	 */
	private void configureAtStartup() throws CoreException {
		List<String> attributes = null;
		List<Object> values = new ArrayList<>(3);
		if (isInstalled()) {
			attributes = new ArrayList<>(3);
			attributes.add(INSTALL_COUNT);
			values.add(new Integer(0));
		}
		if (isExpired()) {
			if (attributes == null) {
				attributes = new ArrayList<>(3);
			}
			// if breakpoint was auto-disabled, re-enable it
			attributes.add(EXPIRED);
			values.add(Boolean.FALSE);
			attributes.add(ENABLED);
			values.add(Boolean.TRUE);
		}
		if (attributes != null) {
			String[] strAttributes = new String[attributes.size()];
			setAttributes(attributes.toArray(strAttributes), values.toArray());
		}
		String[] listeners = readBreakpointListeners();
		if (listeners.length > 0) {
			fBreakpointListenerIds = new ArrayList<>();
			for (String listener : listeners) {
				fBreakpointListenerIds.add(listener);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getHitCount()
	 */
	@Override
	public int getHitCount() throws CoreException {
		return ensureMarker().getAttribute(HIT_COUNT, -1);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#setHitCount(int)
	 */
	@Override
	public void setHitCount(int count) throws CoreException {
		if (getHitCount() != count) {
			if (!isEnabled() && count > -1) {
				setAttributes(new String[] { ENABLED, HIT_COUNT, EXPIRED },
						new Object[] { Boolean.TRUE, new Integer(count),
								Boolean.FALSE });
			} else {
				setAttributes(new String[] { HIT_COUNT, EXPIRED },
						new Object[] { new Integer(count), Boolean.FALSE });
			}
			recreate();
		}
	}

	protected String getMarkerMessage(int hitCount, int suspendPolicy) {
		StringBuffer buff = new StringBuffer();
		if (hitCount > 0) {
			buff.append(MessageFormat
					.format(JDIDebugBreakpointMessages.JavaBreakpoint___Hit_Count___0___1,
							new Object[] { Integer.toString(hitCount) }));
			buff.append(' ');
		}
		String suspendPolicyString;
		if (suspendPolicy == IJavaBreakpoint.SUSPEND_THREAD) {
			suspendPolicyString = JDIDebugBreakpointMessages.JavaBreakpoint__suspend_policy__thread__1;
		} else {
			suspendPolicyString = JDIDebugBreakpointMessages.JavaBreakpoint__suspend_policy__VM__2;
		}

		buff.append(suspendPolicyString);
		return buff.toString();
	}

	/**
	 * Sets whether this breakpoint's hit count has expired.
	 */
	public void setExpired(boolean expired) throws CoreException {
		setAttribute(EXPIRED, expired);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getSuspendPolicy()
	 */
	@Override
	public int getSuspendPolicy() throws CoreException {
		return ensureMarker().getAttribute(SUSPEND_POLICY,
				IJavaBreakpoint.SUSPEND_THREAD);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#setSuspendPolicy(int)
	 */
	@Override
	public void setSuspendPolicy(int suspendPolicy) throws CoreException {
		if (getSuspendPolicy() != suspendPolicy) {
			setAttribute(SUSPEND_POLICY, suspendPolicy);
			recreate();
		}
	}

	/**
	 * Notifies listeners this breakpoint is to be added to the given target.
	 *
	 * @param target
	 *            debug target
	 */
	protected void fireAdding(IJavaDebugTarget target) {
		JDIDebugPlugin plugin = JDIDebugPlugin.getDefault();
		if (plugin != null) {
			plugin.fireBreakpointAdding(target, this);
		}
	}

	/**
	 * Notifies listeners this breakpoint has been removed from the given
	 * target.
	 *
	 * @param target
	 *            debug target
	 */
	protected void fireRemoved(IJavaDebugTarget target) {
		JDIDebugPlugin plugin = JDIDebugPlugin.getDefault();
		if (plugin != null) {
			plugin.fireBreakpointRemoved(target, this);
			setInstalledIn(target, false);
		}
	}

	/**
	 * Notifies listeners this breakpoint has been installed in the given
	 * target.
	 *
	 * @param target
	 *            debug target
	 */
	protected void fireInstalled(IJavaDebugTarget target) {
		JDIDebugPlugin plugin = JDIDebugPlugin.getDefault();
		if (plugin != null && !isInstalledIn(target)) {
			plugin.fireBreakpointInstalled(target, this);
			setInstalledIn(target, true);
		}
	}

	/**
	 * Returns whether this breakpoint is installed in the given target.
	 *
	 * @param target
	 * @return whether this breakpoint is installed in the given target
	 */
	protected boolean isInstalledIn(IJavaDebugTarget target) {
		return fInstalledTargets != null && fInstalledTargets.contains(target);
	}

	/**
	 * Sets this breakpoint as installed in the given target
	 *
	 * @param target
	 * @param installed
	 *            whether installed
	 */
	protected void setInstalledIn(IJavaDebugTarget target, boolean installed) {
		if (installed) {
			if (fInstalledTargets == null) {
				fInstalledTargets = new HashSet<>();
			}
			fInstalledTargets.add(target);
		} else {
			if (fInstalledTargets != null) {
				fInstalledTargets.remove(target);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaBreakpoint#setThreadFilter(org.eclipse
	 * .jdt.debug.core.IJavaThread)
	 */
	@Override
	public void setThreadFilter(IJavaThread thread) throws CoreException {
		if (!(thread.getDebugTarget() instanceof JDIDebugTarget)
				|| !(thread instanceof JDIThread)) {
			return;
		}
		JDIDebugTarget target = (JDIDebugTarget) thread.getDebugTarget();
		if (thread != fFilteredThreadsByTarget.put(target, thread)) {
			// recreate the breakpoint only if it is not the same thread

			// Other breakpoints set attributes on the underlying
			// marker and the marker changes are eventually
			// propagated to the target. The target then asks the
			// breakpoint to update its request. Since thread filters
			// are transient properties, they are not set on
			// the marker. Thus we must update the request
			// here.
			recreate(target);
			fireChanged();
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse
	 * .debug.core.DebugEvent[])
	 */
	@Override
	public void handleDebugEvents(DebugEvent[] events) {
		for (DebugEvent event : events) {
			if (event.getKind() == DebugEvent.TERMINATE) {
				Object source = event.getSource();
				if (!(source instanceof JDIThread)) {
					return;
				}
				try {
					cleanupForThreadTermination((JDIThread) source);
				} catch (VMDisconnectedException exception) {
					// Thread death often occurs at shutdown.
					// A VMDisconnectedException trying to
					// update the breakpoint request is
					// acceptable.
				}
			}
		}
	}

	/**
	 * Removes cached information relevant to this thread which has terminated.
	 *
	 * Remove thread filters for terminated threads
	 *
	 * Subclasses may override but need to call super.
	 */
	protected void cleanupForThreadTermination(JDIThread thread) {
		JDIDebugTarget target = (JDIDebugTarget) thread.getDebugTarget();
		try {
			if (thread == getThreadFilter(target)) {
				removeThreadFilter(target);
			}
		} catch (CoreException exception) {
			JDIDebugPlugin.log(exception);
		}
	}

	/**
	 * EventRequest does not support thread filters, so they can't be set
	 * generically here. However, each of the breakpoint subclasses of
	 * EventRequest do support thread filters. So subclasses can set thread
	 * filters on their specific request type.
	 */
	protected abstract void setRequestThreadFilter(EventRequest request,
			ThreadReference thread);

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaBreakpoint#getThreadFilter(org.eclipse
	 * .jdt.debug.core.IJavaDebugTarget)
	 */
	@Override
	public IJavaThread getThreadFilter(IJavaDebugTarget target) {
		return fFilteredThreadsByTarget.get(target);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getThreadFilters()
	 */
	@Override
	public IJavaThread[] getThreadFilters() {
		IJavaThread[] threads = null;
		Collection<IJavaThread> values = fFilteredThreadsByTarget.values();
		threads = new IJavaThread[values.size()];
		values.toArray(threads);
		return threads;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaBreakpoint#removeThreadFilter(org.eclipse
	 * .jdt.debug.core.IJavaDebugTarget)
	 */
	@Override
	public void removeThreadFilter(IJavaDebugTarget javaTarget)
			throws CoreException {
		if (!(javaTarget instanceof JDIDebugTarget)) {
			return;
		}
		JDIDebugTarget target = (JDIDebugTarget) javaTarget;
		if (fFilteredThreadsByTarget.remove(target) != null) {
			recreate(target);
			fireChanged();
		}
	}

	/**
	 * Returns whether this breakpoint should be installed in the given
	 * reference type in the given target according to registered breakpoint
	 * listeners.
	 *
	 * @param target
	 *            debug target
	 * @param type
	 *            reference type or <code>null</code> if this breakpoint is not
	 *            installed in a specific type
	 */
	protected boolean queryInstallListeners(JDIDebugTarget target,
			ReferenceType type) {
		JDIDebugPlugin plugin = JDIDebugPlugin.getDefault();
		if (plugin != null) {
			IJavaType jt = null;
			if (type != null) {
				jt = JDIType.createType(target, type);
			}
			return plugin.fireInstalling(target, this, jt);
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaBreakpoint#addInstanceFilter(org.eclipse
	 * .jdt.debug.core.IJavaObject)
	 */
	@Override
	public void addInstanceFilter(IJavaObject object) throws CoreException {
		if (fInstanceFilters == null) {
			fInstanceFilters = new ArrayList<>();
		}
		if (!fInstanceFilters.contains(object)) {
			fInstanceFilters.add(object);
			recreate((JDIDebugTarget) object.getDebugTarget());
			fireChanged();
		}
	}

	/**
	 * Change notification when there are no marker changes. If the marker does
	 * not exist, do not fire a change notification (the marker may not exist if
	 * the associated project was closed).
	 */
	protected void fireChanged() {
		DebugPlugin plugin = DebugPlugin.getDefault();
		if (plugin != null && markerExists()) {
			plugin.getBreakpointManager().fireBreakpointChanged(this);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getInstanceFilters()
	 */
	@Override
	public IJavaObject[] getInstanceFilters() {
		if (fInstanceFilters == null || fInstanceFilters.isEmpty()) {
			return fgEmptyInstanceFilters;
		}
		return fInstanceFilters
				.toArray(new IJavaObject[fInstanceFilters.size()]);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaBreakpoint#removeInstanceFilter(org.eclipse
	 * .jdt.debug.core.IJavaObject)
	 */
	@Override
	public void removeInstanceFilter(IJavaObject object) throws CoreException {
		if (fInstanceFilters == null) {
			return;
		}
		if (fInstanceFilters.remove(object)) {
			recreate((JDIDebugTarget) object.getDebugTarget());
			fireChanged();
		}
	}

	/**
	 * An attribute of this breakpoint has changed - recreate event requests in
	 * all targets.
	 */
	protected void recreate() throws CoreException {
		DebugPlugin plugin = DebugPlugin.getDefault();
		if (plugin != null) {
			IDebugTarget[] targets = plugin.getLaunchManager()
					.getDebugTargets();
			for (IDebugTarget target : targets) {
				MultiStatus multiStatus = new MultiStatus(
						JDIDebugPlugin.getUniqueIdentifier(),
						JDIDebugPlugin.ERROR,
						JDIDebugBreakpointMessages.JavaBreakpoint_Exception,
						null);
				IJavaDebugTarget jdiTarget = target
						.getAdapter(IJavaDebugTarget.class);
				if (jdiTarget instanceof JDIDebugTarget) {
					try {
						recreate((JDIDebugTarget) jdiTarget);
					} catch (CoreException e) {
						multiStatus.add(e.getStatus());
					}
				}
				if (!multiStatus.isOK()) {
					throw new CoreException(multiStatus);
				}
			}
		}
	}

	/**
	 * Recreate this breakpoint in the given target, as long as the target
	 * already contains this breakpoint.
	 *
	 * @param target
	 *            the target in which to re-create the breakpoint
	 */
	protected void recreate(JDIDebugTarget target) throws CoreException {
		if (target.isAvailable() && target.getBreakpoints().contains(this)) {
			removeRequests(target);
			createRequests(target);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.debug.core.model.Breakpoint#setEnabled(boolean)
	 */
	@Override
	public void setEnabled(boolean enabled) throws CoreException {
		super.setEnabled(enabled);
		recreate();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#supportsInstanceFilters()
	 */
	@Override
	public boolean supportsInstanceFilters() {
		return true;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#supportsThreadFilters()
	 */
	@Override
	public boolean supportsThreadFilters() {
		return true;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaBreakpoint#addBreakpointListener(java
	 * .lang.String)
	 */
	@Override
	public synchronized void addBreakpointListener(String identifier)
			throws CoreException {
		if (fBreakpointListenerIds == null) {
			fBreakpointListenerIds = new ArrayList<>();
		}
		if (!fBreakpointListenerIds.contains(identifier)) {
			fBreakpointListenerIds.add(identifier);
			writeBreakpointListeners();
		}
	}

	/**
	 * Writes the current breakpoint listener collection to the underlying
	 * marker.
	 *
	 * @throws CoreException
	 */
	private void writeBreakpointListeners() throws CoreException {
		StringBuffer buf = new StringBuffer();
		Iterator<String> iterator = fBreakpointListenerIds.iterator();
		while (iterator.hasNext()) {
			buf.append(iterator.next());
			if (iterator.hasNext()) {
				buf.append(","); //$NON-NLS-1$
			}
		}
		setAttribute(BREAKPOINT_LISTENERS, buf.toString());
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.jdt.debug.core.IJavaBreakpoint#removeBreakpointListener(java
	 * .lang.String)
	 */
	@Override
	public synchronized boolean removeBreakpointListener(String identifier)
			throws CoreException {
		if (fBreakpointListenerIds != null) {
			if (fBreakpointListenerIds.remove(identifier)) {
				writeBreakpointListeners();
				return true;
			}
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#getBreakpointListeners()
	 */
	@Override
	public synchronized String[] getBreakpointListeners() throws CoreException {
		// use the cache in case the underlying marker has been deleted
		if (fBreakpointListenerIds == null) {
			return new String[0];
		}
		return fBreakpointListenerIds
				.toArray(new String[fBreakpointListenerIds.size()]);
	}

	/**
	 * Reads breakpoint listeners from the underlying marker.
	 *
	 * @return breakpoint listener identifiers stored in this breakpoint's
	 *         marker
	 * @throws CoreException
	 *             if no marker
	 */
	private String[] readBreakpointListeners() throws CoreException {
		String value = ensureMarker().getAttribute(BREAKPOINT_LISTENERS,
				(String) null);
		if (value == null) {
			return new String[0];
		}
		return value.split(","); //$NON-NLS-1$
	}
}
