blob: 09cc0345c75c1f0c20d750b39c9c221fe7860dc2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2011 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.util.Map;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.jdt.debug.core.IJavaClassPrepareBreakpoint;
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
import org.eclipse.jdt.internal.debug.core.model.JDIThread;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.event.ClassPrepareEvent;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.request.EventRequest;
/**
* Class prepare breakpoint.
*
* @since 3.0
*/
public class JavaClassPrepareBreakpoint extends JavaBreakpoint implements
IJavaClassPrepareBreakpoint {
public static final String JAVA_CLASS_PREPARE_BREAKPOINT = "org.eclipse.jdt.debug.javaClassPrepareBreakpointMarker"; //$NON-NLS-1$
/**
* Class prepare breakpoint attribute storing the type of member this
* breakpoint is associated with (value
* <code>"org.eclipse.jdt.debug.core.memberType"</code>), encoded as an
* integer.
*/
protected static final String MEMBER_TYPE = "org.eclipse.jdt.debug.core.memberType"; //$NON-NLS-1$
/**
* Creates and returns a Java class prepare breakpoint for the given type.
*
* @param resource
* the resource on which to create the associated breakpoint
* marker
* @param typeName
* the fully qualified name of the type for which to create the
* breakpoint
* @param memberType
* one of <code>TYPE_CLASS</code> or <code>TYPE_INTERFACE</code>
* @param charStart
* the first character index associated with the breakpoint, or
* -1 if unspecified, in the source file in which the breakpoint
* is set
* @param charEnd
* the last character index associated with the breakpoint, or -1
* if unspecified, in the source file in which the breakpoint is
* set
* @param add
* whether to add this breakpoint to the breakpoint manager
* @return a Java class prepare breakpoint
* @exception DebugException
* if unable to create the associated marker due to a lower
* level exception.
*/
public JavaClassPrepareBreakpoint(final IResource resource,
final String typeName, final int memberType, final int charStart,
final int charEnd, final boolean add, final Map<String, Object> attributes)
throws DebugException {
IWorkspaceRunnable wr = new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
// create the marker
setMarker(resource.createMarker(JAVA_CLASS_PREPARE_BREAKPOINT));
// add attributes
attributes.put(IBreakpoint.ID, getModelIdentifier());
attributes.put(IMarker.CHAR_START, Integer.valueOf(charStart));
attributes.put(IMarker.CHAR_END, Integer.valueOf(charEnd));
attributes.put(TYPE_NAME, typeName);
attributes.put(MEMBER_TYPE, Integer.valueOf(memberType));
attributes.put(ENABLED, Boolean.TRUE);
attributes.put(SUSPEND_POLICY, Integer.valueOf(getDefaultSuspendPolicy()));
ensureMarker().setAttributes(attributes);
register(add);
}
};
run(getMarkerRule(resource), wr);
}
public JavaClassPrepareBreakpoint() {
}
/**
* Creates event requests for the given target
*/
@Override
protected void createRequests(JDIDebugTarget target) throws CoreException {
if (target.isTerminated() || shouldSkipBreakpoint()) {
return;
}
String referenceTypeName = getTypeName();
if (referenceTypeName == null) {
return;
}
ClassPrepareRequest request = target.createClassPrepareRequest(
referenceTypeName, null, false);
configureRequestHitCount(request);
updateEnabledState(request, target);
registerRequest(request, target);
// TODO: do we show anything for types already loaded?
incrementInstallCount();
}
/**
* Remove the given request from the given target. If the request is the
* breakpoint request associated with this breakpoint, decrement the install
* count.
*/
@Override
protected void deregisterRequest(EventRequest request, JDIDebugTarget target)
throws CoreException {
target.removeJDIEventListener(this, request);
// A request may be getting deregistered 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 (getMarker().exists()) {
decrementInstallCount();
}
}
/*
* (non-Javadoc)
*
* Not supported for class prepare breakpoints.
*
* @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#
* addInstanceFilter(com.sun.jdi.request.EventRequest,
* com.sun.jdi.ObjectReference)
*/
@Override
protected void addInstanceFilter(EventRequest request,
ObjectReference object) {
}
/*
* (non-Javadoc)
*
* This method not used for class prepare breakpoints.
*
* @see
* org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#newRequest
* (org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget,
* com.sun.jdi.ReferenceType)
*/
@Override
protected EventRequest[] newRequests(JDIDebugTarget target,
ReferenceType type) throws CoreException {
return null;
}
/*
* (non-Javadoc)
*
* Not supported for class prepare breakpoints.
*
* @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#
* setRequestThreadFilter(com.sun.jdi.request.EventRequest,
* com.sun.jdi.ThreadReference)
*/
@Override
protected void setRequestThreadFilter(EventRequest request,
ThreadReference thread) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#
* handleClassPrepareEvent(com.sun.jdi.event.ClassPrepareEvent,
* org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget)
*/
@Override
public boolean handleClassPrepareEvent(ClassPrepareEvent event,
JDIDebugTarget target, boolean suspendVote) {
try {
if (isEnabled()
&& event.referenceType().name().equals(getTypeName())) {
ThreadReference threadRef = event.thread();
JDIThread thread = target.findThread(threadRef);
if (thread == null || thread.isIgnoringBreakpoints()) {
return true;
}
return handleBreakpointEvent(event, thread, suspendVote);
}
} catch (CoreException e) {
}
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#
* classPrepareComplete(com.sun.jdi.event.Event,
* org.eclipse.jdt.internal.debug.core.model.JDIThread, boolean)
*/
@Override
protected void classPrepareComplete(Event event, JDIThread thread,
boolean suspend, EventSet eventSet) {
thread.completeBreakpointHandling(this, suspend, true, eventSet);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jdt.debug.core.IJavaClassPrepareBreakpoint#getMemberType()
*/
@Override
public int getMemberType() throws CoreException {
return ensureMarker().getAttribute(MEMBER_TYPE,
IJavaClassPrepareBreakpoint.TYPE_CLASS);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jdt.debug.core.IJavaBreakpoint#supportsInstanceFilters()
*/
@Override
public boolean supportsInstanceFilters() {
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 {
throw new CoreException(new Status(IStatus.ERROR,
JDIDebugModel.getPluginIdentifier(),
DebugException.REQUEST_FAILED,
JDIDebugBreakpointMessages.JavaClassPrepareBreakpoint_2, null));
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jdt.debug.core.IJavaBreakpoint#setThreadFilter(org.eclipse
* .jdt.debug.core.IJavaThread)
*/
@Override
public void setThreadFilter(IJavaThread thread) throws CoreException {
throw new CoreException(new Status(IStatus.ERROR,
JDIDebugModel.getPluginIdentifier(),
DebugException.REQUEST_FAILED,
JDIDebugBreakpointMessages.JavaClassPrepareBreakpoint_3, null));
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jdt.debug.core.IJavaBreakpoint#supportsThreadFilters()
*/
@Override
public boolean supportsThreadFilters() {
return false;
}
}