blob: a47f30e69e67bac80c106a42382c6f75226ed6a0 [file] [log] [blame]
package org.eclipse.jdt.internal.debug.core;
import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.internal.debug.core.IJavaDebugConstants;
import org.eclipse.jdt.debug.core.IJavaMethodEntryBreakpoint;
import com.sun.jdi.*;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.MethodEntryEvent;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.MethodEntryRequest;
public class JavaMethodEntryBreakpoint extends JavaLineBreakpoint implements IJavaMethodEntryBreakpoint {
static String fMarkerType= IJavaDebugConstants.JAVA_METHOD_ENTRY_BREAKPOINT;
public JavaMethodEntryBreakpoint() {
}
/**
* Creates and returns a method entry breakpoint in the
* given method.
* If hitCount is > 0, the breakpoint will suspend execution when it is
* "hit" the specified number of times. Note: the breakpoint is not
* added to the breakpoint manager - it is merely created.
*
* @param method the method in which to suspend on entry
* @param hitCount the number of times the breakpoint will be hit before
* suspending execution - 0 if it should always suspend
* @return a method entry breakpoint
* @exception DebugException if unable to create the breakpoint marker due
* to a lower level exception.
*/
public JavaMethodEntryBreakpoint(final IMethod method, final int hitCount) throws DebugException {
IWorkspaceRunnable wr= new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
// determine the resource to associate the marker with
IResource resource= null;
resource= method.getUnderlyingResource();
if (resource == null) {
resource= method.getJavaProject().getProject();
}
// create the marker
fMarker= resource.createMarker(fMarkerType);
// find the source range if available
int start = -1;
int end = -1;
ISourceRange range = method.getSourceRange();
if (range != null) {
start = range.getOffset();
end = start + range.getLength() - 1;
}
// configure the standard attributes
setLineBreakpointAttributes(getPluginIdentifier(), true, -1, start, end);
// configure the type handle and hit count
setTypeAndHitCount(method.getDeclaringType(), hitCount);
// configure the method handle
setMethod(method);
// configure the marker as a Java marker
IMarker marker = ensureMarker();
Map attributes= marker.getAttributes();
JavaCore.addJavaElementMarkerAttributes(attributes, method);
marker.setAttributes(attributes);
// Lastly, add the breakpoint manager
addToBreakpointManager();
}
};
run(wr);
}
/**
* A method entry breakpoint has been added.
* Create or update the request.
*/
public void addToTarget(JDIDebugTarget target) throws CoreException {
IType type = getType();
String className = type.getFullyQualifiedName();
MethodEntryRequest request;
try {
request= target.getEventRequestManager().createMethodEntryRequest();
request.addClassFilter(className);
request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
int hitCount = getHitCount();
if (hitCount > 0) {
request.putProperty(IJavaDebugConstants.HIT_COUNT, new Integer(hitCount));
}
request.setEnabled(isEnabled());
} catch (VMDisconnectedException e) {
return;
} catch (RuntimeException e) {
logError(e);
return;
}
registerRequest(target, request);
}
/**
* Update the hit count associated with this method entry breakpoint
* in the given request
*/
protected EventRequest updateHitCount(EventRequest request, JDIDebugTarget target) throws CoreException {
if (hasHitCountChanged(request) || (isExpired(request) && isEnabled())) {
try {
int hitCount = getHitCount();
Integer hc = null;
if (hitCount > 0) {
hc = new Integer(hitCount);
}
request.putProperty(IJavaDebugConstants.HIT_COUNT, hc);
} catch (VMDisconnectedException e) {
} catch (RuntimeException e) {
logError(e);
}
}
return request;
}
/**
* Sets the <code>METHOD_HANDLE</code> attribute of this breakpoint, associated
* with the given IMethod.
*/
public void setMethod(IMethod method) throws CoreException {
String handle = method.getHandleIdentifier();
setMethodHandleIdentifier(handle);
}
/**
* Sets the <code>METHOD_HANDLE</code> attribute of this breakpoint.
*/
public void setMethodHandleIdentifier(String identifier) throws CoreException {
ensureMarker().setAttribute(IJavaDebugConstants.METHOD_HANDLE, identifier);
}
/**
* Handles a method entry event. If this method entry event is
* in a method that a method entry breakpoint has been set for,
* dispatch the event to the correct breakpoint.
*/
public boolean handleEvent(Event genericEvent, JDIDebugTarget target) {
if (!(genericEvent instanceof MethodEntryEvent)) {
return true;
}
MethodEntryEvent event= (MethodEntryEvent) genericEvent;
Method enteredMethod = event.method();
String enteredMethodName= enteredMethod.name();
MethodEntryRequest request = (MethodEntryRequest)event.request();
try {
Object[] nameSignature= getMethodNameSignature();
if (nameSignature != null && nameSignature[0].equals(enteredMethodName) &&
nameSignature[1].equals(enteredMethod.signature())) {
// simulate hit count
Integer count = (Integer)request.getProperty(IJavaDebugConstants.HIT_COUNT);
if (count != null) {
return handleHitCountMethodEntryBreakpoint(event, count, target);
} else {
// no hit count - suspend
doSuspend(event.thread(), target);
return false;
}
} else {
return true;
}
} catch (CoreException e) {
logError(e);
}
return true;
}
/**
* Resume the given thread in the given target
*/
protected void doResume(ThreadReference thread, JDIDebugTarget target) {
if (!target.hasPendingEvents()) {
target.resume(thread);
}
}
/**
* Suspend the given thread in the given target
*/
protected void doSuspend(ThreadReference threadRef, JDIDebugTarget target) {
JDIThread thread= target.findThread(threadRef);
if (thread == null) {
target.resume(threadRef);
return;
} else {
thread.handleSuspendForBreakpoint(this);
}
}
protected boolean handleHitCountMethodEntryBreakpoint(MethodEntryEvent event, Integer count, JDIDebugTarget target) {
// decrement count and suspend if 0
int hitCount = count.intValue();
if (hitCount > 0) {
hitCount--;
count = new Integer(hitCount);
event.request().putProperty(IJavaDebugConstants.HIT_COUNT, count);
if (hitCount == 0) {
// the count has reached 0, breakpoint hit
doSuspend(event.thread(), target);
try {
// make a note that we auto-disabled the breakpoint
// order is important here...see methodEntryChanged
setExpired(true);
setEnabled(false);
} catch (CoreException e) {
logError(e);
}
return false;
} else {
// count still > 0, keep running
return true;
}
} else {
// hit count expired, keep running
return true;
}
}
/**
* @see IJavaLineBreakpoint#getMember()
*/
public IMember getMember() throws CoreException {
return getMethod();
}
/**
* @see IJavaLineBreakpoint#getMethod()
*/
public IMethod getMethod() throws CoreException {
String handle = getMethodHandleIdentifier();
if (handle != null) {
return (IMethod)JavaCore.create(handle);
}
return null;
}
protected String[] getMethodNameSignature() throws CoreException {
String[] nameSignature= new String[2];
IMethod aMethod= getMethod();
if (aMethod.isConstructor()) {
nameSignature[0]= "<init>"; //$NON-NLS-1$
} else {
nameSignature[0]= aMethod.getElementName();
}
nameSignature[1]= aMethod.getSignature();
return nameSignature;
}
}