/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.debug.core.breakpoints;

import java.text.MessageFormat;
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.Platform;
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.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.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) {
			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()) {
				if (this instanceof JavaLineBreakpoint) {
					JavaLineBreakpoint lbp = (JavaLineBreakpoint) this;
					if (lbp.hasCondition()) {
						return;
					}
				}
				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, Integer.valueOf(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(Integer.valueOf(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, Integer.valueOf(count),
								Boolean.FALSE });
			} else {
				setAttributes(new String[] { HIT_COUNT, EXPIRED },
						new Object[] { Integer.valueOf(count), Boolean.FALSE });
			}
			recreate();
		}
	}

	protected String getMarkerMessage(int hitCount, int suspendPolicy) {
		StringBuilder buff = new StringBuilder();
		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 {
		StringBuilder buf = new StringBuilder();
		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$
	}
}
