diff options
author | Darin Wright | 2004-03-13 04:20:39 +0000 |
---|---|---|
committer | Darin Wright | 2004-03-13 04:20:39 +0000 |
commit | 01ddf3ffc028f94a1f35604156ca2fbe228b5025 (patch) | |
tree | 58c35f970f7c80fd6b891f88f680e44cd26c9812 /org.eclipse.jdt.debug/model | |
parent | 28efecbcdecaa4a291bf15f32206ae7432e07f7d (diff) | |
download | eclipse.jdt.debug-01ddf3ffc028f94a1f35604156ca2fbe228b5025.tar.gz eclipse.jdt.debug-01ddf3ffc028f94a1f35604156ca2fbe228b5025.tar.xz eclipse.jdt.debug-01ddf3ffc028f94a1f35604156ca2fbe228b5025.zip |
Bug 46530 - class load/prepare breakpoint
Diffstat (limited to 'org.eclipse.jdt.debug/model')
7 files changed, 331 insertions, 3 deletions
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaBreakpoint.java index dd4ba915e..2c5de46e0 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaBreakpoint.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaBreakpoint.java @@ -151,12 +151,14 @@ public interface IJavaBreakpoint extends IBreakpoint { /** * Adds the given object to the list of objects in which this * breakpoint is restricted to suspend execution. Has no effect - * if the object has already been added.<br> - * + * if the object has already been added. Note that clients should + * first ensure that a breakpoint supports instance filters. + * <p> * Note: This implementation will add more than one filter. However, if there is * more than one instance filter for a debug target, the breakpoint will never be hit * in that target, as the current context cannot be two different instances at the * same time. + * </p> * * @param object instance filter to add * @exception CoreException if unable to add the given instance filter @@ -176,6 +178,14 @@ public interface IJavaBreakpoint extends IBreakpoint { public void removeInstanceFilter(IJavaObject object) throws CoreException; /** + * Returns whether this breakpoints supports instance filters. + * + * @return whether this breakpoints supports instance filters + * @since 3.0 + */ + public boolean supportsInstanceFilters(); + + /** * Returns the current set of active instance filters. * * @return the current set of active instance filters. @@ -183,5 +193,14 @@ public interface IJavaBreakpoint extends IBreakpoint { * @since 2.1 */ public IJavaObject[] getInstanceFilters() throws CoreException; + + /** + * Returns whether this breakpoints supports thread filters. + * + * @return whether this breakpoints supports thread filters + * @since 3.0 + */ + public boolean supportsThreadFilters(); + } diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaClassPrepareBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaClassPrepareBreakpoint.java new file mode 100644 index 000000000..032de1f56 --- /dev/null +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaClassPrepareBreakpoint.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.debug.core; + +import org.eclipse.core.runtime.CoreException; + +/** + * A breakpoint that suspends execution when a class is prepared in + * a target VM. + * + * @since 3.0 + */ +public interface IJavaClassPrepareBreakpoint extends IJavaBreakpoint { + + /** + * Constant indicating a class prepare breakpoint is associated with a + * class type. + */ + public static final int TYPE_CLASS = 0; + /** + * Constant indicating a class prepare breakpoint is associated with an + * interface type. + */ + public static final int TYPE_INTERFACE = 1; + + /** + * Returns a constant indicating what kind of type this breakpoint + * is associated with. + * + * @return one of <code>TYPE_CLASS</code> or <code>TYPE_INTERFACE</code> + * @throws CoreException if unable to retrieve the attribute + */ + public int getMemberType() throws CoreException; +} diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java index 24a74400a..48a91d069 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java @@ -27,6 +27,7 @@ import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IProcess; import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin; +import org.eclipse.jdt.internal.debug.core.breakpoints.JavaClassPrepareBreakpoint; import org.eclipse.jdt.internal.debug.core.breakpoints.JavaExceptionBreakpoint; import org.eclipse.jdt.internal.debug.core.breakpoints.JavaLineBreakpoint; import org.eclipse.jdt.internal.debug.core.breakpoints.JavaMethodBreakpoint; @@ -602,4 +603,29 @@ public class JDIDebugModel { public static void savePreferences() { JDIDebugPlugin.getDefault().savePluginPreferences(); } + + /** + * Creates and returns a class prepare breakpoint for a type with the given name. + * The marker associated with the breakpoint will be created on the specified resource. + * + * @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 register whether to add this breakpoint to the breakpoint manager + * @param attributes a map of client defined attributes that should be assigned + * to the underlying breakpoint marker on creation or <code>null</code> if none. + * @return an exception breakpoint + * @exception CoreException If this method fails. Reasons include:<ul> + *<li>Failure creating underlying marker. The exception's status contains + * the underlying exception responsible for the failure.</li></ul> + * @since 3.0 + */ + public static IJavaClassPrepareBreakpoint createClassPrepareBreakpoint(IResource resource, String typeName, int memberType, boolean register, Map attributes) throws CoreException { + if (attributes == null) { + attributes = new HashMap(10); + } + return new JavaClassPrepareBreakpoint(resource, typeName, memberType, register, attributes); + } } diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JDIDebugBreakpointMessages.properties b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JDIDebugBreakpointMessages.properties index 015b10e99..f8add4fb6 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JDIDebugBreakpointMessages.properties +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JDIDebugBreakpointMessages.properties @@ -33,3 +33,5 @@ JavaMethodBreakpoint.Unable_to_create_breakpoint_request_-_VM_disconnected._1=Un JavaTargetPatternBreakpoint.Unable_to_add_breakpoint_-_VM_disconnected._1=Unable to add breakpoint - VM disconnected. +JavaClassPrepareBreakpoint.2=Class prepare breakpoint does not support instance filters +JavaClassPrepareBreakpoint.3=Class prepare breakpoint does not support thread filters diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java index 7276b5a4e..3eed40f19 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java @@ -1148,4 +1148,16 @@ public abstract class JavaBreakpoint extends Breakpoint implements IJavaBreakpoi recreate(); } + /* (non-Javadoc) + * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#supportsInstanceFilters() + */ + public boolean supportsInstanceFilters() { + return true; + } + /* (non-Javadoc) + * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#supportsThreadFilters() + */ + public boolean supportsThreadFilters() { + return true; + } } diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaClassPrepareBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaClassPrepareBreakpoint.java new file mode 100644 index 000000000..125d753a7 --- /dev/null +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaClassPrepareBreakpoint.java @@ -0,0 +1,203 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.debug.core.breakpoints; + +import java.util.Map; + +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.request.ClassPrepareRequest; +import com.sun.jdi.request.EventRequest; + +/** + * Class prepare breakpoint. + * + * @since 3.0 + */ +public class JavaClassPrepareBreakpoint extends JavaBreakpoint implements IJavaClassPrepareBreakpoint { + + private 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 an exception breakpoint for the + * given (throwable) type. Caught and uncaught specify where the exception + * should cause thread suspensions - that is, in caught and/or uncaught locations. + * Checked indicates if the given exception is a checked exception. + * @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 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 boolean add, final Map attributes) throws DebugException { + IWorkspaceRunnable wr= new IWorkspaceRunnable() { + + 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(TYPE_NAME, typeName); + attributes.put(MEMBER_TYPE, new Integer(memberType)); + attributes.put(ENABLED, Boolean.TRUE); + + ensureMarker().setAttributes(attributes); + + register(add); + } + + }; + run(null, wr); + } + + public JavaClassPrepareBreakpoint() { + } + + /** + * Creates event requests for the given target + */ + 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); + 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. + */ + 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) + */ + 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) + */ + protected EventRequest newRequest(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) + */ + 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) + */ + public boolean handleClassPrepareEvent(ClassPrepareEvent event, JDIDebugTarget target) { + 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, target, thread); + } + } catch (CoreException e) { + } + return true; + } + /* (non-Javadoc) + * @see org.eclipse.jdt.debug.core.IJavaClassPrepareBreakpoint#getMemberType() + */ + public int getMemberType() throws CoreException { + return ensureMarker().getAttribute(MEMBER_TYPE, IJavaClassPrepareBreakpoint.TYPE_CLASS); + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#supportsInstanceFilters() + */ + public boolean supportsInstanceFilters() { + return false; + } + /* (non-Javadoc) + * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#addInstanceFilter(org.eclipse.jdt.debug.core.IJavaObject) + */ + public void addInstanceFilter(IJavaObject object) throws CoreException { + throw new CoreException(new Status(IStatus.ERROR, JDIDebugModel.getPluginIdentifier(), DebugException.REQUEST_FAILED, JDIDebugBreakpointMessages.getString("JavaClassPrepareBreakpoint.2"), null)); //$NON-NLS-1$ + } + /* (non-Javadoc) + * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#setThreadFilter(org.eclipse.jdt.debug.core.IJavaThread) + */ + public void setThreadFilter(IJavaThread thread) throws CoreException { + throw new CoreException(new Status(IStatus.ERROR, JDIDebugModel.getPluginIdentifier(), DebugException.REQUEST_FAILED, JDIDebugBreakpointMessages.getString("JavaClassPrepareBreakpoint.3"), null)); //$NON-NLS-1$ + } + /* (non-Javadoc) + * @see org.eclipse.jdt.debug.core.IJavaBreakpoint#supportsThreadFilters() + */ + public boolean supportsThreadFilters() { + return false; + } +} diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java index 6d5c8dcf0..9287ba152 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIDebugTarget.java @@ -968,6 +968,28 @@ public class JDIDebugTarget extends JDIDebugElement implements IJavaDebugTarget, * @exception CoreException if unable to create the request */ public ClassPrepareRequest createClassPrepareRequest(String classPattern, String classExclusionPattern) throws CoreException { + return createClassPrepareRequest(classPattern, classExclusionPattern, true); + } + + /** + * Creates, enables and returns a class prepare request for the + * specified class name in this target. Can specify a class exclusion filter + * as well. + * This is a utility method used by event requesters that need to + * create class prepare requests. + * + * @param classPattern regular expression specifying the pattern of + * class names that will cause the event request to fire. Regular + * expressions may begin with a '*', end with a '*', or be an exact + * match. + * @param classExclusionPattern regular expression specifying the pattern of + * class names that will not cause the event request to fire. Regular + * expressions may begin with a '*', end with a '*', or be an exact + * match. May be <code>null</code>. + * @param enabled whether to enable the event request + * @exception CoreException if unable to create the request + */ + public ClassPrepareRequest createClassPrepareRequest(String classPattern, String classExclusionPattern, boolean enabled) throws CoreException { EventRequestManager manager= getEventRequestManager(); if (!isAvailable() || manager == null) { requestFailed(JDIDebugModelMessages.getString("JDIDebugTarget.Unable_to_create_class_prepare_request_-_VM_disconnected._2"), null); //$NON-NLS-1$ @@ -980,7 +1002,9 @@ public class JDIDebugTarget extends JDIDebugElement implements IJavaDebugTarget, req.addClassExclusionFilter(classExclusionPattern); } req.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); - req.enable(); + if (enabled) { + req.enable(); + } } catch (RuntimeException e) { targetRequestFailed(JDIDebugModelMessages.getString("JDIDebugTarget.Unable_to_create_class_prepare_request._3"), e); //$NON-NLS-1$ // execution will not reach here |