| package org.eclipse.dltk.internal.debug.core.model; |
| |
| 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.debug.core.DebugException; |
| import org.eclipse.debug.core.model.IBreakpoint; |
| import org.eclipse.dltk.debug.core.DLTKDebugPlugin; |
| import org.eclipse.dltk.debug.core.model.IScriptExceptionBreakpoint; |
| |
| public class ScriptExceptionBreakpoint extends AbstractScriptBreakpoint |
| implements IScriptExceptionBreakpoint { |
| |
| private static final String SCRIPT_EXCEPTION_BREAKPOINT = "org.eclipse.dltk.debug.scriptExceptionBreakpointMarker"; //$NON-NLS-1$ |
| |
| /** |
| * Breakpoint attribute storing the fully qualified name of the type this |
| * breakpoint is located in. (value |
| * <code>"org.eclipse.jdt.debug.core.typeName"</code>). This attribute is a |
| * <code>String</code>. |
| */ |
| protected static final String TYPE_NAME = DLTKDebugPlugin.PLUGIN_ID |
| + ".typeName"; //$NON-NLS-1$ |
| /** |
| * Exception breakpoint attribute storing the suspend on caught value (value |
| * <code>"org.eclipse.dltk.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 |
| * excecution to suspend . |
| */ |
| protected static final String CAUGHT = DLTKDebugPlugin.PLUGIN_ID |
| + ".caught"; //$NON-NLS-1$ |
| /** |
| * Exception breakpoint attribute storing the suspend on uncaught value |
| * (value <code>"org.eclipse.dltk.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 excecution to suspend. |
| */ |
| protected static final String UNCAUGHT = DLTKDebugPlugin.PLUGIN_ID |
| + ".uncaught"; //$NON-NLS-1$ |
| /** |
| * Allows the user to specify whether we should suspend if subclasses of the |
| * specified exception are thrown/caught |
| */ |
| protected static final String SUSPEND_ON_SUBCLASSES = DLTKDebugPlugin.PLUGIN_ID |
| + ".suspend_on_subclasses"; //$NON-NLS-1$ |
| |
| /** |
| * Name of the exception that was actually hit (could be a subtype of the |
| * type that is being caught). |
| */ |
| protected String fExceptionName = null; |
| |
| public ScriptExceptionBreakpoint() { |
| } |
| |
| /** |
| * Creates and returns an exception breakpoint for the given 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 ScriptExceptionBreakpoint(final String debugModelId, |
| final IResource resource, final String exceptionName, |
| final boolean caught, final boolean uncaught, final boolean add, |
| final Map<String, Object> attributes) throws DebugException { |
| IWorkspaceRunnable wr = monitor -> { |
| // create the marker |
| setMarker(resource.createMarker(SCRIPT_EXCEPTION_BREAKPOINT)); |
| |
| // add general breakpoint attributes |
| addScriptBreakpointAttributes(attributes, debugModelId, true); |
| |
| // add exception breakpoint attributes |
| attributes.put(TYPE_NAME, exceptionName); |
| attributes.put(CAUGHT, Boolean.valueOf(caught)); |
| attributes.put(UNCAUGHT, Boolean.valueOf(uncaught)); |
| |
| ensureMarker().setAttributes(attributes); |
| |
| register(add); |
| }; |
| run(getMarkerRule(resource), wr); |
| } |
| |
| /** |
| * 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); |
| } |
| |
| @Override |
| public boolean isCaught() throws CoreException { |
| return ensureMarker().getAttribute(CAUGHT, false); |
| } |
| |
| @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); |
| } |
| } |
| |
| @Override |
| public void setSuspendOnSubclasses(boolean suspend) throws CoreException { |
| if (suspend != isSuspendOnSubclasses()) { |
| setAttribute(SUSPEND_ON_SUBCLASSES, suspend); |
| } |
| } |
| |
| @Override |
| public boolean isSuspendOnSubclasses() throws CoreException { |
| return ensureMarker().getAttribute(SUSPEND_ON_SUBCLASSES, false); |
| } |
| |
| @Override |
| public boolean isUncaught() throws CoreException { |
| return ensureMarker().getAttribute(UNCAUGHT, false); |
| } |
| |
| @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); |
| } |
| } |
| |
| /** |
| * Sets the name of the exception that was last hit |
| * |
| * @param name |
| * fully qualified exception name |
| */ |
| protected void setExceptionTypeName(String name) { |
| fExceptionName = name; |
| } |
| |
| @Override |
| public String getExceptionTypeName() { |
| return fExceptionName; |
| } |
| |
| private static final String[] UPDATABLE_ATTRS = new String[] { |
| IBreakpoint.ENABLED, AbstractScriptBreakpoint.HIT_CONDITION, |
| AbstractScriptBreakpoint.HIT_VALUE, CAUGHT, UNCAUGHT, |
| SUSPEND_ON_SUBCLASSES }; |
| |
| @Override |
| public String[] getUpdatableAttributes() { |
| return UPDATABLE_ATTRS; |
| } |
| |
| @Override |
| public String getTypeName() throws CoreException { |
| return (String) ensureMarker().getAttribute(TYPE_NAME); |
| } |
| } |