| /******************************************************************************* |
| * Copyright (c) 2000, 2005 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.ui; |
| |
| |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.debug.core.model.IBreakpoint; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IField; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IMember; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.debug.core.IJavaBreakpoint; |
| import org.eclipse.jdt.debug.core.IJavaLineBreakpoint; |
| import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint; |
| import org.eclipse.jdt.debug.core.IJavaWatchpoint; |
| |
| /** |
| * Utility class for Java breakpoints |
| */ |
| public class BreakpointUtils { |
| |
| /** |
| * Marker attribute storing the handle id of the |
| * Java element associated with a Java breakpoint |
| */ |
| private static final String HANDLE_ID = JDIDebugUIPlugin.getUniqueIdentifier() + ".JAVA_ELEMENT_HANDLE_ID"; //$NON-NLS-1$ |
| |
| /** |
| * Marker attribute used to denote a run to line breakpoint |
| */ |
| private static final String RUN_TO_LINE = JDIDebugUIPlugin.getUniqueIdentifier() + ".run_to_line"; //$NON-NLS-1$ |
| |
| /** |
| * Marker attribute used to denote the start of the region within a Java |
| * member that the breakpoint is located within. |
| */ |
| private static final String MEMBER_START = JDIDebugUIPlugin.getUniqueIdentifier() + ".member_start"; //$NON-NLS-1$ |
| |
| /** |
| * Marker attribute used to denote the end of the region within a Java |
| * member that the breakpoint is located within. |
| */ |
| private static final String MEMBER_END = JDIDebugUIPlugin.getUniqueIdentifier() + ".member_end"; //$NON-NLS-1$ |
| |
| /** |
| * Returns the resource on which a breakpoint marker should |
| * be created for the given member. The resource returned is the |
| * associated file, or project in the case of a class file in |
| * a jar. |
| * |
| * @param member member in which a breakpoint is being created |
| * @return resource the resource on which a breakpoint marker |
| * should be created |
| */ |
| public static IResource getBreakpointResource(IMember member) { |
| ICompilationUnit cu = member.getCompilationUnit(); |
| if (cu != null && cu.isWorkingCopy()) { |
| member = (IMember)member.getPrimaryElement(); |
| } |
| IResource res = member.getResource(); |
| if (res == null) { |
| res = member.getJavaProject().getProject(); |
| } |
| return res; |
| } |
| |
| /** |
| * Returns the type that the given Java breakpoint refers to |
| * |
| * @param breakpoint Java breakpoint |
| * @return the type the breakpoint is associated with |
| */ |
| public static IType getType(IJavaBreakpoint breakpoint) { |
| String handle = breakpoint.getMarker().getAttribute(HANDLE_ID, null); |
| if (handle != null) { |
| IJavaElement je = JavaCore.create(handle); |
| if (je != null) { |
| if (je instanceof IType) { |
| return (IType)je; |
| } |
| if (je instanceof IMember) { |
| return ((IMember)je).getDeclaringType(); |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the member associated with the line number of |
| * the given breakpoint. |
| * |
| * @param breakpoint Java line breakpoint |
| * @return member at the given line number in the type |
| * associated with the breakpoint |
| * @exception CoreException if an exception occurs accessing |
| * the breakpoint |
| */ |
| public static IMember getMember(IJavaLineBreakpoint breakpoint) throws CoreException { |
| if (breakpoint instanceof IJavaMethodBreakpoint) { |
| return getMethod((IJavaMethodBreakpoint)breakpoint); |
| } |
| if (breakpoint instanceof IJavaWatchpoint) { |
| return getField((IJavaWatchpoint)breakpoint); |
| } |
| |
| int start = breakpoint.getCharStart(); |
| int end = breakpoint.getCharEnd(); |
| |
| IType type = getType(breakpoint); |
| |
| if (start == -1 && end == -1) { |
| start= breakpoint.getMarker().getAttribute(MEMBER_START, -1); |
| end= breakpoint.getMarker().getAttribute(MEMBER_END, -1); |
| } |
| |
| IMember member = null; |
| if ((type != null && type.exists()) && (end >= start) && (start >= 0)) { |
| member= binSearch(type, start, end); |
| } |
| if (member == null) { |
| member= type; |
| } |
| return member; |
| } |
| |
| /** |
| * Searches the given source range of the container for a member that is |
| * not the same as the given type. |
| */ |
| protected static IMember binSearch(IType type, int start, int end) throws JavaModelException { |
| IJavaElement je = getElementAt(type, start); |
| if (je != null && !je.equals(type)) { |
| return asMember(je); |
| } |
| if (end > start) { |
| je = getElementAt(type, end); |
| if (je != null && !je.equals(type)) { |
| return asMember(je); |
| } |
| int mid = ((end - start) / 2) + start; |
| if (mid > start) { |
| je = binSearch(type, start + 1, mid); |
| if (je == null) { |
| je = binSearch(type, mid + 1, end - 1); |
| } |
| return asMember(je); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the given Java element if it is an |
| * <code>IMember</code>, otherwise <code>null</code>. |
| * |
| * @param element Java element |
| * @return the given element if it is a type member, |
| * otherwise <code>null</code> |
| */ |
| private static IMember asMember(IJavaElement element) { |
| if (element instanceof IMember) { |
| return (IMember)element; |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the element at the given position in the given type |
| */ |
| protected static IJavaElement getElementAt(IType type, int pos) throws JavaModelException { |
| if (type.isBinary()) { |
| return type.getClassFile().getElementAt(pos); |
| } |
| return type.getCompilationUnit().getElementAt(pos); |
| } |
| |
| /** |
| * Adds attributes to the given attribute map:<ul> |
| * <li>Java element handle id</li> |
| * <li>Attributes defined by <code>JavaCore</code></li> |
| * </ul> |
| * |
| * @param attributes the attribute map to use |
| * @param element the Java element associated with the breakpoint |
| * @exception CoreException if an exception occurs configuring |
| * the marker |
| */ |
| public static void addJavaBreakpointAttributes(Map attributes, IJavaElement element) { |
| String handleId = element.getHandleIdentifier(); |
| attributes.put(HANDLE_ID, handleId); |
| JavaCore.addJavaElementMarkerAttributes(attributes, element); |
| } |
| |
| /** |
| * Adds attributes to the given attribute map:<ul> |
| * <li>Java element handle id</li> |
| * <li>Member start position</li> |
| * <li>Member end position</li> |
| * <li>Attributes defined by <code>JavaCore</code></li> |
| * </ul> |
| * |
| * @param attributes the attribute map to use |
| * @param element the Java element associated with the breakpoint |
| * @param memberStart the start position of the Java member that the breakpoint is positioned within |
| * @param memberEnd the end position of the Java member that the breakpoint is positioned within |
| * @exception CoreException if an exception occurs configuring |
| * the marker |
| */ |
| public static void addJavaBreakpointAttributesWithMemberDetails(Map attributes, IJavaElement element, int memberStart, int memberEnd) { |
| addJavaBreakpointAttributes(attributes, element); |
| attributes.put(MEMBER_START, new Integer(memberStart)); |
| attributes.put(MEMBER_END, new Integer(memberEnd)); |
| } |
| |
| /** |
| * Adds attributes to the given attribute map to make the |
| * breakpoint a run-to-line breakpoint:<ul> |
| * <li>PERSISTED = false</li> |
| * <li>RUN_TO_LINE = true</li> |
| * </ul> |
| * |
| * @param attributes the attribute map to use |
| * @param element the Java element associated with the breakpoint |
| * @exception CoreException if an exception occurs configuring |
| * the marker |
| */ |
| public static void addRunToLineAttributes(Map attributes) { |
| attributes.put(IBreakpoint.PERSISTED, Boolean.FALSE); |
| attributes.put(RUN_TO_LINE, Boolean.TRUE); |
| } |
| |
| /** |
| * Returns the method associated with the method entry |
| * breakpoint. |
| * |
| * @param breakpoint Java method entry breakpoint |
| * @return method |
| */ |
| public static IMethod getMethod(IJavaMethodBreakpoint breakpoint) { |
| String handle = breakpoint.getMarker().getAttribute(HANDLE_ID, null); |
| if (handle != null) { |
| IJavaElement je = JavaCore.create(handle); |
| if (je != null) { |
| if (je instanceof IMethod) { |
| return (IMethod)je; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the field associated with the watchpoint. |
| * |
| * @param breakpoint Java watchpoint |
| * @return field |
| */ |
| public static IField getField(IJavaWatchpoint breakpoint) { |
| String handle = breakpoint.getMarker().getAttribute(HANDLE_ID, null); |
| if (handle != null) { |
| IJavaElement je = JavaCore.create(handle); |
| if (je != null) { |
| if (je instanceof IField) { |
| return (IField)je; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns whether the given breakpoint is a run to line |
| * breakpoint |
| * |
| * @param breakpoint line breakpoint |
| * @return whether the given breakpoint is a run to line |
| * breakpoint |
| */ |
| public static boolean isRunToLineBreakpoint(IJavaLineBreakpoint breakpoint) { |
| return breakpoint.getMarker().getAttribute(RUN_TO_LINE, false); |
| } |
| |
| /** |
| * Returns whether the given breakpoint is a compilation |
| * problem breakpoint or uncaught exception breakpoint |
| * |
| * @param breakpoint breakpoint |
| * @return whether the given breakpoint is a compilation error breakpoint or |
| * uncaught exception breakpoint |
| */ |
| public static boolean isProblemBreakpoint(IBreakpoint breakpoint) { |
| return breakpoint == JavaDebugOptionsManager.getDefault().getSuspendOnCompilationErrorBreakpoint() || |
| breakpoint == JavaDebugOptionsManager.getDefault().getSuspendOnUncaughtExceptionBreakpoint(); |
| } |
| } |