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.core.runtime.IProgressMonitor;
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 attributes) throws DebugException {
IWorkspaceRunnable wr = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
// 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.
*/
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);
}
/**
* @see IScriptExceptionBreakpoint#isCaught()
*/
public boolean isCaught() throws CoreException {
return ensureMarker().getAttribute(CAUGHT, false);
}
/**
* @see IscriptExceptionBreakpoint#setCaught(boolean)
*/
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);
}
}
/* (non-Javadoc)
* @see org.eclipse.dltk.debug.core.IJavaExceptionBreakpoint#setSuspendOnSubclasses(boolean)
*/
public void setSuspendOnSubclasses(boolean suspend) throws CoreException {
if (suspend != isSuspendOnSubclasses()) {
setAttribute(SUSPEND_ON_SUBCLASSES, suspend);
}
}
/* (non-Javadoc)
* @see org.eclipse.dltk.debug.core.IJavaExceptionBreakpoint#isSuspendOnSubclasses()
*/
public boolean isSuspendOnSubclasses() throws CoreException {
return ensureMarker().getAttribute(SUSPEND_ON_SUBCLASSES, false);
}
/**
* @see IJavaExceptionBreakpoint#isUncaught()
*/
public boolean isUncaught() throws CoreException {
return ensureMarker().getAttribute(UNCAUGHT, false);
}
/**
* @see IJavaExceptionBreakpoint#setUncaught(boolean)
*/
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;
}
/* (non-Javadoc)
* @see org.eclipse.dltk.debug.core.IJavaExceptionBreakpoint#getExceptionTypeName()
*/
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 };
public String[] getUpdatableAttributes() {
return UPDATABLE_ATTRS;
}
public String getTypeName() throws CoreException {
return (String) ensureMarker().getAttribute(TYPE_NAME);
}
}