blob: 82a864e7cf2d0b902f5477eb9c88989e4e319d20 [file] [log] [blame]
package org.eclipse.jdt.debug.core;
/*
* Licensed Materials - Property of IBM,
* WebSphere Studio Workbench
* (c) Copyright IBM Corp 2000
*/
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.internal.debug.core.*;
import com.sun.jdi.VirtualMachine;
import java.util.Map;
/**
* The JDI debug model plug-in provides an implementation of a debug
* model based on JDI. This class provides utility methods for
* creating debug targets and breakpoints specific to the JDI debug
* model, as well as accessing attributes of breakpoints created by
* this debug model.
* <p>
* To provide access to behavior and information specific to the JDI
* debug model, a set of interfaces are defined which extend the base
* set of debug element interfaces. For example, <code>IJavaStackFrame</code>
* is declared to extend <code>IStackFrame</code>, and provides methods
* specific to this debug model. The specialized interfaces are also
* available as adapters from the debug elements generated from this
* model.
* </p>
* <p>
* Clients are not intended to instantiate or subclass this class;
* this class provides static utility methods only.
* </p>
* <b>Note:</b> This class/interface is part of an interim API that is still under development and expected to
* change significantly before reaching stability. It is being made available at this early stage to solicit feedback
* from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
* (repeatedly) as the API evolves.
* </p>
* @see IJavaDebugTarget
* @see IJavaThread
* @see IJavaStackFrame
* @see IJavaVariable
*/
public class JDIDebugModel {
/**
* The last breakpoint that was created, or <code>null</code>
*/
private static IMarker fgBreakpoint= null;
/**
* The most recently created debug target
*/
private static IJavaDebugTarget fgTarget = null;
/**
* Not to be instantiated.
*/
private JDIDebugModel() {
super();
}
/**
* Creates and returns a debug target for the given VM, with
* the specified name, and associates the debug target with the
* given process for console I/O. The allow terminate flag specifies whether
* the debug target will support termination (<code>ITerminate</code>).
* The allow disconnect flag specifies whether the debug target will
* support disconnection (<code>IDisconnect</code>). Launching the actual
* VM is a client responsibility.
*
* @param vm the VM do create a debug target for
* @param name the name to associate with the VM, which will be
* returned from <code>IDebugTarget.getName</code>. If <code>null</code>
* the name will be retrieved from the underlying VM.
* @param process the process to associate with the debug target,
* which will be returned from <code>IDebugTarget.getProcess</code>
* @param allowTermiante specifies if the target will support termianation
* @param allowDisconnect specifies if the target will support disconnection
* @return a debug target
* @see org.eclipse.debug.core.model.ITerminate
* @see org.eclipse.debug.core.model.IDisconnect
*/
public static IDebugTarget newDebugTarget(final VirtualMachine vm, final String name, final IProcess process, final boolean allowTerminate, final boolean allowDisconnect) {
fgTarget = null;
IWorkspaceRunnable r = new IWorkspaceRunnable() {
public void run(IProgressMonitor m) {
fgTarget= new JDIDebugTarget(vm, name, allowTerminate, allowDisconnect, process);
}
};
try {
ResourcesPlugin.getWorkspace().run(r, null);
} catch (CoreException e) {
DebugJavaUtils.logError(e);
}
return fgTarget;
}
/**
* Returns the identifier for this JDI debug model plug-in
*
* @return plugin identifier
*/
public static String getPluginIdentifier() {
return JDIDebugPlugin.getDefault().getDescriptor().getUniqueIdentifier();
}
/**
* Creates and returns a line breakpoint in the
* given type, at the given line number. If a character range within the
* line is known, it may be specified by charStart/charEnd.
* If hitCount is > 0, the breakpoint will suspend execution when it is
* "hit" the specified number of times. Note: the breakpoint is not
* added to the breakpoint manager - it is merely created.
*
* @param type the type in which to create the breakpoint
* @param lineNumber the lineNumber on which the breakpoint is created - line
* numbers are 1 based, associated with the compilation unit in which
* the type is defined
* @param charStart the first character index associated with the breakpoint,
* or -1 if unspecified
* @param charEnd the last character index associated with the breakpoint,
* or -1 if unspecified
* @param hitCount the number of times the breakpoint will be hit before
* suspending execution - 0 if it should always suspend
* @return a line breakpoint
* @exception DebugException if unable to create the breakpoint marker due
* to a lower level exception.
*/
public static IMarker createLineBreakpoint(IType type, int lineNumber, int charStart, int charEnd, int hitCount) throws DebugException {
return createLineBreakpointCommon(type, lineNumber, charStart, charEnd, hitCount, IJavaDebugConstants.JAVA_LINE_BREAKPOINT);
}
/**
* Creates and returns a run-to-line breakpoint in the
* given type, at the given line number. If a character range within the
* line is known, it may be specified by charStart/charEnd. Run-to-line
* breakpoints have a hit count of 1.
* Note: the breakpoint is not added to the breakpoint manager
* - it is merely created.
*
* @param type the type in which to create the breakpoint
* @param lineNumber the lineNumber on which the breakpoint is created - line
* numbers are 1 based, associated with the compilation unit in which
* the type is defined
* @param charStart the first character index associated with the breakpoint,
* or -1 if unspecified
* @param charEnd the last character index associated with the breakpoint,
* or -1 if unspecified
* @return a run-to-line breakpoint
* @exception DebugException if unable to create the breakpoint marker due
* to a lower level exception.
*/
public static IMarker createRunToLineBreakpoint(IType type, int lineNumber, int charStart, int charEnd) throws DebugException {
return createLineBreakpointCommon(type, lineNumber, charStart, charEnd, 1, IJavaDebugConstants.JAVA_RUN_TO_LINE_BREAKPOINT);
}
/**
* Common method for creating line breakpoints, either 'regular' or 'run to line'
*/
private static IMarker createLineBreakpointCommon(final IType type, final int lineNumber, final int charStart, final int charEnd, final int hitCount, final String exceptionType) throws DebugException {
fgBreakpoint= null;
IWorkspaceRunnable wr= new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
IResource resource= null;
resource= type.getUnderlyingResource();
if (resource == null) {
resource= type.getJavaProject().getProject();
}
// create the marker
fgBreakpoint= resource.createMarker(exceptionType);
DebugPlugin.getDefault().getBreakpointManager().configureLineBreakpoint(fgBreakpoint, getPluginIdentifier(), true, lineNumber, charStart, charEnd);
// configure the hit count and type handle
DebugJavaUtils.setTypeAndHitCount(fgBreakpoint, type, hitCount);
// configure the marker as a Java marker
Map attributes= fgBreakpoint.getAttributes();
JavaCore.addJavaElementMarkerAttributes(attributes, type);
fgBreakpoint.setAttributes(attributes);
}
};
try {
ResourcesPlugin.getWorkspace().run(wr, null);
} catch (CoreException e) {
throw new DebugException(e.getStatus());
}
return fgBreakpoint;
}
/**
* 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.
* Note: the breakpoint is not added to the breakpoint manager
* - it is merely created.
*
* @param type 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
* @return an exception breakpoint
* @exception DebugException if unable to create the breakpoint marker due
* to a lower level exception.
*/
public static IMarker createExceptionBreakpoint(final IType exception, final boolean caught, final boolean uncaught, final boolean checked) throws DebugException {
// determine the resource to associate the marker with
fgBreakpoint= null;
IWorkspaceRunnable wr= new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
IResource resource= null;
resource= exception.getUnderlyingResource();
if (resource == null) {
resource= exception.getJavaProject().getProject();
}
// if the exception breakpoint already exists in the breakpoint mgr.,
// just use it
IMarker existing= findExistingExceptionBreakpoint(exception);
if (existing != null) {
fgBreakpoint= existing;
return;
}
// create the marker
fgBreakpoint= resource.createMarker(IJavaDebugConstants.JAVA_EXCEPTION_BREAKPOINT);
// configure the standard attributes
DebugPlugin.getDefault().getBreakpointManager().configureBreakpoint(fgBreakpoint, getPluginIdentifier(), true);
// configure caught, uncaught, checked, and the type attributes
DebugJavaUtils.configureExceptionBreakpoint(fgBreakpoint, caught, uncaught, checked, exception);
// configure the marker as a Java marker
Map attributes= fgBreakpoint.getAttributes();
JavaCore.addJavaElementMarkerAttributes(attributes, exception);
fgBreakpoint.setAttributes(attributes);
}
};
try {
ResourcesPlugin.getWorkspace().run(wr, null);
} catch (CoreException e) {
throw new DebugException(e.getStatus());
}
return fgBreakpoint;
}
private static IMarker findExistingExceptionBreakpoint(IType type) {
IBreakpointManager manager= DebugPlugin.getDefault().getBreakpointManager();
IMarker[] allBreakpoints= manager.getBreakpoints(IJavaDebugConstants.JAVA_EXCEPTION_BREAKPOINT);
for (int i = 0; i < allBreakpoints.length; i++) {
IMarker bp= allBreakpoints[i];
if (DebugJavaUtils.getType(bp).equals(type)) {
return bp;
}
}
return null;
}
/**
* Creates and returns a method entry breakpoint in the
* given method.
* If hitCount is > 0, the breakpoint will suspend execution when it is
* "hit" the specified number of times. Note: the breakpoint is not
* added to the breakpoint manager - it is merely created.
*
* @param method the method in which to suspend on entry
* @param hitCount the number of times the breakpoint will be hit before
* suspending execution - 0 if it should always suspend
* @return a method entry breakpoint
* @exception DebugException if unable to create the breakpoint marker due
* to a lower level exception.
*/
public static IMarker createMethodEntryBreakpoint(final IMethod method, final int hitCount) throws DebugException {
// determine the resource to associate the marker with
fgBreakpoint= null;
IWorkspaceRunnable wr= new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
IResource resource= null;
resource= method.getUnderlyingResource();
if (resource == null) {
resource= method.getJavaProject().getProject();
}
// create the marker
fgBreakpoint= resource.createMarker(IJavaDebugConstants.JAVA_METHOD_ENTRY_BREAKPOINT);
// find the source range if available
int start = -1;
int end = -1;
ISourceRange range = method.getSourceRange();
if (range != null) {
start = range.getOffset();
end = start + range.getLength() - 1;
}
// configure the standard attributes
DebugPlugin.getDefault().getBreakpointManager().configureLineBreakpoint(fgBreakpoint, getPluginIdentifier(), true, -1, start, end);
// configure the type handle and hit count
DebugJavaUtils.setTypeAndHitCount(fgBreakpoint, method.getDeclaringType(), hitCount);
// configure the method handle
DebugJavaUtils.setMethod(fgBreakpoint, method);
// configure the marker as a Java marker
Map attributes= fgBreakpoint.getAttributes();
JavaCore.addJavaElementMarkerAttributes(attributes, method);
fgBreakpoint.setAttributes(attributes);
}
};
try {
ResourcesPlugin.getWorkspace().run(wr, null);
} catch (CoreException e) {
throw new DebugException(e.getStatus());
}
return fgBreakpoint;
}
/**
* Returns the hit count of the given breakpoint or -1 if the attribute is not set.
*
* @param breakpoint the breakpoint
* @return hit count, or -1
*/
public static int getHitCount(IMarker breakpoint) {
return DebugJavaUtils.getHitCount(breakpoint);
}
/**
* Sets the hit count of the given breakpoint
*
* @param breakpoint the breakpoint
* @param hitCount the number of times the breakpoint is hit before suspending execution
* @exception CoreException if an exception occurrs updating the marker
*/
public static void setHitCount(IMarker breakpoint, int hitCount) throws CoreException {
DebugJavaUtils.setHitCount(breakpoint, hitCount);
}
/**
* Returns the member the given breakpoint is installed in,
* or <code>null</code> if a member is not determinable.
*
* @param breakpoint the breakpoint
* @return a member, or <code>null</code>
*/
public static IMember getMember(IMarker breakpoint) {
try {
return DebugJavaUtils.getMember(breakpoint);
} catch (CoreException e) {
return null;
}
}
/**
* Returns the method the given breakpoint is installed in
* or <code>null</code> if breakpoint is not installed in a method.
*
* @param breakpoint the breakpoint
* @return a method, or <code>null</code>
*/
public static IMethod getMethod(IMarker breakpoint) {
return DebugJavaUtils.getMethod(breakpoint);
}
/**
* Returns the type the given breakpoint is installed in
* or <code>null</code> if breakpoint is not installed in a type. If
* the breakpoint is an exception breakpoint, the type associated with
* the exception is returned. For a method entry breakpoint, the
* method's declaring type is retured.
*
* @param breakpoint the breakpoint
* @return a type, or <code>nulll</code>
*/
public static IType getType(IMarker breakpoint) {
return DebugJavaUtils.getType(breakpoint);
}
/**
* Returns whether the given breakpoint is an exception
* breakpoint that will suspend in caught locations.
*
* @param breakpoint the breakpoint
* @return whether the given breakpoint is an exception
* breakpoint that will suspend in caught locations
*/
public static boolean isCaught(IMarker breakpoint) {
return DebugJavaUtils.isCaught(breakpoint);
}
/**
* Returns whether the given breakpoint is an exception
* breakpoint for a checked exception.
*
* @param breakpoint the breakpoint
* @return whether the given breakpoint is an exception
* breakpoint for a checked exception
*/
public static boolean isChecked(IMarker breakpoint) {
return DebugJavaUtils.isChecked(breakpoint);
}
/**
* Returns whether the given breakpoint
* is an exception breakpoint.
*
* @param breakpoint the breakpoint
* @return whether the given breakpoint
* is an exception breakpoint
*/
public static boolean isExceptionBreakpoint(IMarker breakpoint) {
return DebugJavaUtils.isExceptionBreakpoint(breakpoint);
}
/**
* Returns whether the given breakpoint is installed in at least one debug target.
*
* @param breakpoint the breakpoint
* @return whether the given breakpoint is installed in at least one debug target
*/
public static boolean isInstalled(IMarker breakpoint) {
return DebugJavaUtils.isInstalled(breakpoint);
}
/**
* Returns whether the given breakpoint is a method entry breakpoint.
*
* @param breakpoint the breakpoint
* @return whether the given breakpoint is a method entry breakpoint
*/
public static boolean isMethodEntryBreakpoint(IMarker breakpoint) {
return DebugJavaUtils.isMethodEntryBreakpoint(breakpoint);
}
/**
* Returns whether the given breakpoint is a run to line breakpoint.
*
* @param breakpoint the breakpoint
* @retrun whether the given breakpoint is a run to line breakpoint
*/
public static boolean isRunToLineBreakpoint(IMarker breakpoint) {
return DebugJavaUtils.isRunToLineBreakpoint(breakpoint);
}
/**
* Returns whether the given breakpoint is an exception
* breakpoint that will suspend in uncaught locations.
*
* @param breakpoint the breakpoint
* @return whether the given breakpoint is an exception
* breakpoint that will suspend in uncaught locations
*/
public static boolean isUncaught(IMarker breakpoint) {
return DebugJavaUtils.isUncaught(breakpoint);
}
}