| /******************************************************************************* |
| * Copyright (c) 2000, 2012 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.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.StringTokenizer; |
| import java.util.regex.Pattern; |
| |
| 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.debug.core.DebugException; |
| import org.eclipse.debug.core.model.IBreakpoint; |
| import org.eclipse.jdt.debug.core.IJavaDebugTarget; |
| import org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint; |
| import org.eclipse.jdt.debug.core.IJavaObject; |
| import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin; |
| import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget; |
| import org.eclipse.jdt.internal.debug.core.model.JDIThread; |
| import org.eclipse.jdt.internal.debug.core.model.JDIValue; |
| |
| import com.sun.jdi.ClassType; |
| import com.sun.jdi.Location; |
| import com.sun.jdi.ObjectReference; |
| import com.sun.jdi.ReferenceType; |
| import com.sun.jdi.ThreadReference; |
| import com.sun.jdi.VMDisconnectedException; |
| import com.sun.jdi.event.Event; |
| import com.sun.jdi.event.ExceptionEvent; |
| import com.sun.jdi.request.EventRequest; |
| import com.sun.jdi.request.EventRequestManager; |
| import com.sun.jdi.request.ExceptionRequest; |
| |
| public class JavaExceptionBreakpoint extends JavaBreakpoint implements |
| IJavaExceptionBreakpoint { |
| |
| public static final String JAVA_EXCEPTION_BREAKPOINT = "org.eclipse.jdt.debug.javaExceptionBreakpointMarker"; //$NON-NLS-1$ |
| |
| /** |
| * Exception breakpoint attribute storing the suspend on caught value (value |
| * <code>"org.eclipse.jdt.debug.core.caught"</code>). This attribute is |
| * stored as a <code>boolean</code>. When this attribute is |
| * <code>true</code>, a caught exception of the associated type will cause |
| * execution to suspend . |
| */ |
| protected static final String CAUGHT = "org.eclipse.jdt.debug.core.caught"; //$NON-NLS-1$ |
| /** |
| * Exception breakpoint attribute storing the suspend on uncaught value |
| * (value <code>"org.eclipse.jdt.debug.core.uncaught"</code>). This |
| * attribute is stored as a <code>boolean</code>. When this attribute is |
| * <code>true</code>, an uncaught exception of the associated type will |
| * cause execution to suspend. |
| */ |
| protected static final String UNCAUGHT = "org.eclipse.jdt.debug.core.uncaught"; //$NON-NLS-1$ |
| /** |
| * Exception breakpoint attribute storing the checked value (value |
| * <code>"org.eclipse.jdt.debug.core.checked"</code>). This attribute is |
| * stored as a <code>boolean</code>, indicating whether an exception is a |
| * checked exception. |
| */ |
| protected static final String CHECKED = "org.eclipse.jdt.debug.core.checked"; //$NON-NLS-1$ |
| |
| /** |
| * Exception breakpoint attribute storing the String value (value |
| * <code>"org.eclipse.jdt.debug.core.filters"</code>). This attribute is |
| * stored as a <code>String</code>, a comma delimited list of class filters. |
| * The filters are applied as inclusion or exclusion depending on |
| * INCLUSIVE_FILTERS. |
| */ |
| protected static final String INCLUSION_FILTERS = "org.eclipse.jdt.debug.core.inclusion_filters"; //$NON-NLS-1$ |
| |
| /** |
| * Exception breakpoint attribute storing the String value (value |
| * <code>"org.eclipse.jdt.debug.core.filters"</code>). This attribute is |
| * stored as a <code>String</code>, a comma delimited list of class filters. |
| * The filters are applied as inclusion or exclusion depending on |
| * INCLUSIVE_FILTERS. |
| */ |
| protected static final String EXCLUSION_FILTERS = "org.eclipse.jdt.debug.core.exclusion_filters"; //$NON-NLS-1$ |
| /** |
| * Allows the user to specify whether we should suspend if subclasses of the |
| * specified exception are thrown/caught |
| * |
| * @since 3.2 |
| */ |
| protected static final String SUSPEND_ON_SUBCLASSES = "org.eclipse.jdt.debug.core.suspend_on_subclasses"; //$NON-NLS-1$ |
| |
| /** |
| * Name of the exception that was actually hit (could be a sub-type of the |
| * type that is being caught). |
| */ |
| protected String fExceptionName = null; |
| |
| /** |
| * The current set of inclusion class filters. |
| */ |
| protected String[] fInclusionClassFilters = null; |
| |
| /** |
| * The current set of inclusion class filters. |
| */ |
| protected String[] fExclusionClassFilters = null; |
| |
| private ObjectReference fLastException; |
| private JDIDebugTarget fLastTarget; |
| |
| public JavaExceptionBreakpoint() { |
| } |
| |
| /** |
| * 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 exceptionName |
| * the fully qualified name of the exception for which to create |
| * the breakpoint |
| * @param caught |
| * whether to suspend in caught locations |
| * @param uncaught |
| * whether to suspend in uncaught locations |
| * @param checked |
| * whether the exception is a checked exception |
| * @param add |
| * whether to add this breakpoint to the breakpoint manager |
| * @return a Java exception breakpoint |
| * @exception DebugException |
| * if unable to create the associated marker due to a lower |
| * level exception. |
| */ |
| public JavaExceptionBreakpoint(final IResource resource, |
| final String exceptionName, final boolean caught, |
| final boolean uncaught, final boolean checked, 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_EXCEPTION_BREAKPOINT)); |
| |
| // add attributes |
| attributes.put(IBreakpoint.ID, getModelIdentifier()); |
| attributes.put(TYPE_NAME, exceptionName); |
| attributes.put(ENABLED, Boolean.TRUE); |
| attributes.put(CAUGHT, Boolean.valueOf(caught)); |
| attributes.put(UNCAUGHT, Boolean.valueOf(uncaught)); |
| attributes.put(CHECKED, Boolean.valueOf(checked)); |
| attributes.put(SUSPEND_POLICY, new Integer( |
| getDefaultSuspendPolicy())); |
| |
| ensureMarker().setAttributes(attributes); |
| |
| register(add); |
| } |
| |
| }; |
| run(getMarkerRule(resource), wr); |
| } |
| |
| /** |
| * Creates a request in the given target to suspend when the given exception |
| * type is thrown. The request is returned installed, configured, and |
| * enabled as appropriate for this breakpoint. |
| */ |
| @Override |
| protected EventRequest[] newRequests(JDIDebugTarget target, |
| ReferenceType type) throws CoreException { |
| if (!isCaught() && !isUncaught()) { |
| return null; |
| } |
| ExceptionRequest request = null; |
| EventRequestManager manager = target.getEventRequestManager(); |
| if (manager == null) { |
| target.requestFailed( |
| JDIDebugBreakpointMessages.JavaExceptionBreakpoint_Unable_to_create_breakpoint_request___VM_disconnected__1, |
| null); |
| return null; |
| } |
| |
| try { |
| request = manager.createExceptionRequest(type, isCaught(), |
| isUncaught()); |
| configureRequest(request, target); |
| } catch (VMDisconnectedException e) { |
| if (target.isAvailable()) { |
| JDIDebugPlugin.log(e); |
| } |
| return null; |
| } catch (RuntimeException e) { |
| target.internalError(e); |
| return null; |
| } |
| return new EventRequest[] { request }; |
| } |
| |
| /** |
| * Enable this exception breakpoint. |
| * |
| * If the exception breakpoint is not catching caught or uncaught, turn both |
| * modes on. If this isn't done, the resulting state (enabled with caught |
| * and uncaught both disabled) is ambiguous. |
| */ |
| @Override |
| public void setEnabled(boolean enabled) throws CoreException { |
| if (enabled) { |
| if (!(isCaught() || isUncaught())) { |
| setAttributes(new String[] { CAUGHT, UNCAUGHT }, new Object[] { |
| Boolean.TRUE, Boolean.TRUE }); |
| } |
| } |
| super.setEnabled(enabled); |
| } |
| |
| /** |
| * Sets the values for whether this breakpoint will suspend execution when |
| * the associated exception is thrown and caught or not caught. |
| */ |
| protected void setCaughtAndUncaught(boolean caught, boolean uncaught) |
| throws CoreException { |
| Object[] values = new Object[] { Boolean.valueOf(caught), |
| Boolean.valueOf(uncaught) }; |
| String[] attributes = new String[] { CAUGHT, UNCAUGHT }; |
| setAttributes(attributes, values); |
| } |
| |
| /** |
| * @see IJavaExceptionBreakpoint#isCaught() |
| */ |
| @Override |
| public boolean isCaught() throws CoreException { |
| return ensureMarker().getAttribute(CAUGHT, false); |
| } |
| |
| /** |
| * @see IJavaExceptionBreakpoint#setCaught(boolean) |
| */ |
| @Override |
| public void setCaught(boolean caught) throws CoreException { |
| if (caught == isCaught()) { |
| return; |
| } |
| setAttribute(CAUGHT, caught); |
| if (caught && !isEnabled()) { |
| setEnabled(true); |
| } else if (!(caught || isUncaught())) { |
| setEnabled(false); |
| } |
| recreate(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint#setSuspendOnSubclasses |
| * (boolean) |
| */ |
| public void setSuspendOnSubclasses(boolean suspend) throws CoreException { |
| if (suspend != isSuspendOnSubclasses()) { |
| setAttribute(SUSPEND_ON_SUBCLASSES, suspend); |
| recreate(); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint#isSuspendOnSubclasses |
| * () |
| */ |
| public boolean isSuspendOnSubclasses() throws CoreException { |
| return ensureMarker().getAttribute(SUSPEND_ON_SUBCLASSES, false); |
| } |
| |
| /** |
| * @see IJavaExceptionBreakpoint#isUncaught() |
| */ |
| @Override |
| public boolean isUncaught() throws CoreException { |
| return ensureMarker().getAttribute(UNCAUGHT, false); |
| } |
| |
| /** |
| * @see IJavaExceptionBreakpoint#setUncaught(boolean) |
| */ |
| @Override |
| public void setUncaught(boolean uncaught) throws CoreException { |
| if (uncaught == isUncaught()) { |
| return; |
| } |
| setAttribute(UNCAUGHT, uncaught); |
| if (uncaught && !isEnabled()) { |
| setEnabled(true); |
| } else if (!(uncaught || isCaught())) { |
| setEnabled(false); |
| } |
| recreate(); |
| } |
| |
| /** |
| * @see IJavaExceptionBreakpoint#isChecked() |
| */ |
| @Override |
| public boolean isChecked() throws CoreException { |
| return ensureMarker().getAttribute(CHECKED, false); |
| } |
| |
| /** |
| * @see JavaBreakpoint#setRequestThreadFilter(EventRequest) |
| */ |
| @Override |
| protected void setRequestThreadFilter(EventRequest request, |
| ThreadReference thread) { |
| ((ExceptionRequest) request).addThreadFilter(thread); |
| } |
| |
| /** |
| * @see JavaBreakpoint#handleBreakpointEvent(Event, JDIDebugTarget, |
| * JDIThread) Decides how to handle an exception being thrown |
| * |
| * @return true if we do not want to suspend false otherwise |
| */ |
| @Override |
| public boolean handleBreakpointEvent(Event event, JDIThread thread, |
| boolean suspendVote) { |
| if (event instanceof ExceptionEvent) { |
| ObjectReference ex = ((ExceptionEvent) event).exception(); |
| fLastTarget = thread.getJavaDebugTarget(); |
| fLastException = ex; |
| String name = null; |
| try { |
| name = ex.type().name(); |
| if (!name.equals(getTypeName())) { |
| if (!isSuspendOnSubclasses() |
| & isSubclass((ClassType) ex.type(), getTypeName())) { |
| return true; |
| } |
| } |
| } catch (VMDisconnectedException e) { |
| return true; |
| } catch (CoreException e) { |
| JDIDebugPlugin.log(e); |
| } catch (RuntimeException e) { |
| try { |
| thread.targetRequestFailed(e.getMessage(), e); |
| } catch (DebugException de) { |
| JDIDebugPlugin.log(e); |
| return false; |
| } |
| } |
| setExceptionName(name); |
| disableTriggerPoint(event); |
| if (getExclusionClassFilters().length >= 1 |
| || getInclusionClassFilters().length >= 1 |
| || filtersIncludeDefaultPackage(fInclusionClassFilters) |
| || filtersIncludeDefaultPackage(fExclusionClassFilters)) { |
| Location location = ((ExceptionEvent) event).location(); |
| String typeName = location.declaringType().name(); |
| boolean defaultPackage = typeName.indexOf('.') == -1; |
| boolean included = true; |
| String[] filters = getInclusionClassFilters(); |
| if (filters.length > 0) { |
| included = matchesFilters(filters, typeName, defaultPackage); |
| } |
| boolean excluded = false; |
| filters = getExclusionClassFilters(); |
| if (filters.length > 0) { |
| excluded = matchesFilters(filters, typeName, defaultPackage); |
| } |
| if (included && !excluded) { |
| return !suspend(thread, suspendVote); |
| } |
| return true; |
| } |
| return !suspend(thread, suspendVote); |
| } |
| return true; |
| } |
| |
| /** |
| * Returns whether the given class type is a subclass of the classes with the |
| * given name. |
| * |
| * @param type |
| * the class type reference |
| * @return true if the specified the class type is a subclass of the class |
| * with the given name |
| * @since 3.2 |
| */ |
| private boolean isSubclass(ClassType type, String typeName) { |
| type = type.superclass(); |
| while (type != null) { |
| if (type.name().equals(typeName)) { |
| return true; |
| } |
| type = type.superclass(); |
| } |
| return false; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#setInstalledIn |
| * (org.eclipse.jdt.debug.core.IJavaDebugTarget, boolean) |
| */ |
| @Override |
| protected void setInstalledIn(IJavaDebugTarget target, boolean installed) { |
| fLastException = null; |
| fLastTarget = null; |
| super.setInstalledIn(target, installed); |
| } |
| |
| /** |
| * Determines of the filters for this exception include the default package |
| * or not |
| * |
| * @param filters |
| * the list of filters to inspect |
| * @return true if any one of the specified filters include the default |
| * package |
| */ |
| protected boolean filtersIncludeDefaultPackage(String[] filters) { |
| for (String filter : filters) { |
| if (filter.length() == 0 || (filter.indexOf('.') == -1)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Returns whether the given type is in the given filter set. |
| * |
| * @param filters |
| * the filter set |
| * @param typeName |
| * fully qualified type name |
| * @param defaultPackage |
| * whether the type name is in the default package |
| * @return boolean |
| */ |
| protected boolean matchesFilters(String[] filters, String typeName, |
| boolean defaultPackage) { |
| for (String filter2 : filters) { |
| String filter = filter2; |
| if (defaultPackage && filter.length() == 0) { |
| return true; |
| } |
| |
| filter = filter.replaceAll("\\.", "\\\\."); //$NON-NLS-1$//$NON-NLS-2$ |
| filter = filter.replaceAll("\\*", "\\.\\*"); //$NON-NLS-1$//$NON-NLS-2$ |
| Pattern pattern = Pattern.compile(filter); |
| if (pattern.matcher(typeName).find()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Sets the name of the exception that was last hit |
| * |
| * @param name |
| * fully qualified exception name |
| */ |
| protected void setExceptionName(String name) { |
| fExceptionName = name; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint#getExceptionTypeName |
| * () |
| */ |
| @Override |
| public String getExceptionTypeName() { |
| return fExceptionName; |
| } |
| |
| /** |
| * @see IJavaExceptionBreakpoint#getFilters() |
| * @deprecated |
| */ |
| @Override |
| @Deprecated |
| public String[] getFilters() { |
| String[] iFilters = getInclusionFilters(); |
| String[] eFilters = getExclusionFilters(); |
| String[] filters = new String[iFilters.length + eFilters.length]; |
| System.arraycopy(iFilters, 0, filters, 0, iFilters.length); |
| System.arraycopy(eFilters, 0, filters, iFilters.length, eFilters.length); |
| return filters; |
| } |
| |
| /** |
| * @see IJavaExceptionBreakpoint#setFilters(String[], boolean) |
| * @deprecated |
| */ |
| @Override |
| @Deprecated |
| public void setFilters(String[] filters, boolean inclusive) |
| throws CoreException { |
| if (inclusive) { |
| setInclusionFilters(filters); |
| } else { |
| setExclusionFilters(filters); |
| } |
| recreate(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint# |
| * configureRequest(com.sun.jdi.request.EventRequest, |
| * org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget) |
| */ |
| @Override |
| protected void configureRequest(EventRequest eRequest, JDIDebugTarget target) |
| throws CoreException { |
| String[] iFilters = getInclusionClassFilters(); |
| String[] eFilters = getExclusionClassFilters(); |
| |
| ExceptionRequest request = (ExceptionRequest) eRequest; |
| |
| if (iFilters.length == 1) { |
| if (eFilters.length == 0) { |
| request.addClassFilter(iFilters[0]); |
| } |
| } else if (eFilters.length == 1) { |
| if (iFilters.length == 0) { |
| request.addClassExclusionFilter(eFilters[0]); |
| } |
| } |
| |
| super.configureRequest(eRequest, target); |
| } |
| |
| /** |
| * Serializes the array of Strings into one comma separated String. Removes |
| * duplicates. |
| */ |
| protected String serializeList(String[] list) { |
| if (list == null) { |
| return ""; //$NON-NLS-1$ |
| } |
| Set<String> set = new HashSet<String>(list.length); |
| StringBuffer buffer = new StringBuffer(); |
| for (int i = 0; i < list.length; i++) { |
| if (i > 0 && i < list.length) { |
| buffer.append(','); |
| } |
| String pattern = list[i]; |
| if (!set.contains(pattern)) { |
| if (pattern.length() == 0) { |
| // serialize the default package |
| pattern = "."; //$NON-NLS-1$ |
| } |
| buffer.append(pattern); |
| set.add(pattern); |
| } |
| } |
| return buffer.toString(); |
| } |
| |
| /** |
| * Parses the comma separated String into an array of Strings |
| */ |
| protected String[] parseList(String listString) { |
| List<String> list = new ArrayList<String>(10); |
| StringTokenizer tokenizer = new StringTokenizer(listString, ","); //$NON-NLS-1$ |
| while (tokenizer.hasMoreTokens()) { |
| String token = tokenizer.nextToken(); |
| if (token.equals(".")) { //$NON-NLS-1$ |
| // serialized form for the default package |
| // @see serializeList(String[]) |
| token = ""; //$NON-NLS-1$ |
| } |
| list.add(token); |
| } |
| return list.toArray(new String[list.size()]); |
| } |
| |
| /** |
| * @see IJavaExceptionBreakpoint#isInclusiveFiltered() |
| * @deprecated |
| */ |
| @Override |
| @Deprecated |
| public boolean isInclusiveFiltered() throws CoreException { |
| return ensureMarker().getAttribute(INCLUSION_FILTERS, "").length() > 0; //$NON-NLS-1$ |
| } |
| |
| protected String[] getInclusionClassFilters() { |
| if (fInclusionClassFilters == null) { |
| try { |
| fInclusionClassFilters = parseList(ensureMarker().getAttribute( |
| INCLUSION_FILTERS, "")); //$NON-NLS-1$ |
| } catch (CoreException ce) { |
| fInclusionClassFilters = new String[] {}; |
| } |
| } |
| return fInclusionClassFilters; |
| } |
| |
| protected void setInclusionClassFilters(String[] filters) { |
| fInclusionClassFilters = filters; |
| } |
| |
| protected String[] getExclusionClassFilters() { |
| if (fExclusionClassFilters == null) { |
| try { |
| fExclusionClassFilters = parseList(ensureMarker().getAttribute( |
| EXCLUSION_FILTERS, "")); //$NON-NLS-1$ |
| } catch (CoreException ce) { |
| fExclusionClassFilters = new String[] {}; |
| } |
| } |
| return fExclusionClassFilters; |
| } |
| |
| protected void setExclusionClassFilters(String[] filters) { |
| fExclusionClassFilters = filters; |
| } |
| |
| /** |
| * @see JavaBreakpoint#installableReferenceType(ReferenceType, |
| * JDIDebugTarget) |
| */ |
| @Override |
| protected boolean installableReferenceType(ReferenceType type, |
| JDIDebugTarget target) throws CoreException { |
| String installableType = getTypeName(); |
| String queriedType = type.name(); |
| if (installableType == null || queriedType == null) { |
| return false; |
| } |
| if (installableType.equals(queriedType)) { |
| return queryInstallListeners(target, type); |
| } |
| |
| return false; |
| } |
| |
| /** |
| * @see org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint#getExclusionFilters() |
| */ |
| @Override |
| public String[] getExclusionFilters() { |
| return getExclusionClassFilters(); |
| } |
| |
| /** |
| * @see org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint#getInclusionFilters() |
| */ |
| @Override |
| public String[] getInclusionFilters() { |
| return getInclusionClassFilters(); |
| } |
| |
| /** |
| * @see org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint#setExclusionFilters(String[]) |
| */ |
| @Override |
| public void setExclusionFilters(String[] filters) throws CoreException { |
| String serializedFilters = serializeList(filters); |
| |
| if (serializedFilters.equals(ensureMarker().getAttribute( |
| EXCLUSION_FILTERS, ""))) { //$NON-NLS-1$ |
| // no change |
| return; |
| } |
| |
| setExclusionClassFilters(filters); |
| |
| setAttribute(EXCLUSION_FILTERS, serializedFilters); |
| recreate(); |
| } |
| |
| /** |
| * @see org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint#setInclusionFilters(String[]) |
| */ |
| @Override |
| public void setInclusionFilters(String[] filters) throws CoreException { |
| String serializedFilters = serializeList(filters); |
| |
| if (serializedFilters.equals(ensureMarker().getAttribute( |
| INCLUSION_FILTERS, ""))) { //$NON-NLS-1$ |
| // no change |
| return; |
| } |
| |
| setInclusionClassFilters(filters); |
| |
| setAttribute(INCLUSION_FILTERS, serializedFilters); |
| recreate(); |
| } |
| |
| /** |
| * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#addInstanceFilter(EventRequest, |
| * ObjectReference) |
| */ |
| @Override |
| protected void addInstanceFilter(EventRequest request, |
| ObjectReference object) { |
| if (request instanceof ExceptionRequest) { |
| ((ExceptionRequest) request).addInstanceFilter(object); |
| } |
| } |
| |
| /** |
| * Returns the last exception object that was encountered by this exception |
| * |
| * TODO: make API in future release. |
| * |
| * @return |
| */ |
| public IJavaObject getLastException() { |
| if (fLastException != null) { |
| return (IJavaObject) JDIValue.createValue(fLastTarget, |
| fLastException); |
| } |
| return null; |
| } |
| } |