| /******************************************************************************* |
| * Copyright (c) 2000, 2011 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.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, new Integer(charStart)); |
| attributes.put(IMarker.CHAR_END, new Integer(charEnd)); |
| attributes.put(TYPE_NAME, typeName); |
| attributes.put(MEMBER_TYPE, new Integer(memberType)); |
| attributes.put(ENABLED, Boolean.TRUE); |
| attributes.put(SUSPEND_POLICY, new Integer( |
| 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; |
| } |
| } |