*** empty log message ***
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaDebugConstants.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaDebugConstants.java
index aea3f56..c8a1f00 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaDebugConstants.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaDebugConstants.java
@@ -21,6 +21,12 @@
 public interface IJavaDebugConstants {

 	

 	/**

+	 * Java breakpoint marker type

+	 * (value <code>"org.eclipse.jdt.debug.javaBreakpoint"</code>).

+	 */

+	public static final String JAVA_BREAKPOINT= "org.eclipse.jdt.debug.javaBreakpoint";

+	

+	/**

 	 * Java line breakpoint marker type

 	 * (value <code>"org.eclipse.jdt.debug.javaLineBreakpoint"</code>).

 	 */

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaThread.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaThread.java
index d174ec0..01bca70 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaThread.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaThread.java
@@ -8,8 +8,7 @@
 import org.eclipse.debug.core.DebugException;

 import org.eclipse.debug.core.model.IThread;

 import org.eclipse.debug.core.model.IVariable;

-import org.eclipse.core.resources.IMarker;

-import org.eclipse.jdt.core.IJavaProject;

+import org.eclipse.jdt.internal.debug.core.JavaBreakpoint;

 

 /**

  * A Java thread is an extension of a regular thread,

@@ -54,7 +53,7 @@
 	 *

 	 * @return breakpoint that caused suspend, or <code>null</code> if none

 	 */

-	IMarker getBreakpoint();

+	JavaBreakpoint getBreakpoint();

 	

 	/**

 	 * Returns a variable with the given name, or <code>null</code> if

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java
index 3771588..7b3e2e3 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/JDIDebugModel.java
@@ -134,303 +134,25 @@
 	 *  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;

+		return (new LineBreakpoint(type, lineNumber, charStart, charEnd, hitCount, IJavaDebugConstants.JAVA_LINE_BREAKPOINT)).getMarker();

 	}

 

-	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;

+	public static IBreakpointManager getBreakpointManager() {

+		return DebugPlugin.getDefault().getBreakpointManager();

 	}

 

 	/**

-	 * Creates and returns a watchpoint on the

-	 * given field.

-	 * If hitCount > 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 field the field on which to suspend (on access or modification)

-	 * @param hitCount the number of times the breakpoint will be hit before

-	 * 	suspending execution - 0 if it should always suspend

-	 * @return a watchpoint

-	 * @exception DebugException if unable to create the breakpoint marker due

-	 * 	to a lower level exception

-	 */

-	public static IMarker createWatchpoint(final IField field, final int hitCount) throws DebugException {

-		

-		fgBreakpoint= null;

-		

-		IWorkspaceRunnable wr= new IWorkspaceRunnable() {

-			

-			public void run(IProgressMonitor monitor) throws CoreException {

-

-				IResource resource = null;

-				ICompilationUnit compilationUnit = getCompilationUnit(field);

-				if (compilationUnit != null) {

-					resource = compilationUnit.getUnderlyingResource();

-				}

-				if (resource == null) {

-					resource = field.getJavaProject().getProject();

-				}

-				

-				fgBreakpoint= resource.createMarker(IJavaDebugConstants.JAVA_WATCHPOINT);

-				

-				// find the source range if available

-				int start = -1;

-				int stop = -1;

-				ISourceRange range = field.getSourceRange();

-				if (range != null) {

-					start = range.getOffset();

-					stop = start + range.getLength() - 1;

-				}

-				// configure the standard attributes

-				DebugPlugin.getDefault().getBreakpointManager().configureLineBreakpoint(fgBreakpoint, getPluginIdentifier(), true, -1, start, stop);

-				// configure the type handle and hit count

-				DebugJavaUtils.setTypeAndHitCount(fgBreakpoint, field.getDeclaringType(), hitCount);

-				// configure the field handle

-				DebugJavaUtils.setField(fgBreakpoint, field);

-				// configure the access and modification flags to defaults

-				DebugJavaUtils.setDefaultAccessAndModification(fgBreakpoint);

-				DebugJavaUtils.setAutoDisabled(fgBreakpoint, false);				

-				

-				

-				// configure the marker as a Java marker

-				Map attributes= fgBreakpoint.getAttributes();

-				JavaCore.addJavaElementMarkerAttributes(attributes, field);

-				fgBreakpoint.setAttributes(attributes);			

-			}

-		};

-		

-		try {

-			ResourcesPlugin.getWorkspace().run(wr, null);

-		} catch (CoreException e) {

-			throw new DebugException(e.getStatus());

-		}

-		

-		return fgBreakpoint;

-	}

-

-	/**

-	 * Returns the underlying compilation unit of an element.

-	 */

-	public static ICompilationUnit getCompilationUnit(IJavaElement element) {

-		if (element instanceof IWorkingCopy) {

-			return (ICompilationUnit) ((IWorkingCopy) element).getOriginalElement();

-		}

-		if (element instanceof ICompilationUnit) {

-			return (ICompilationUnit) element;

-		}		

-		IJavaElement parent = element.getParent();

-		if (parent != null) {

-			return getCompilationUnit(parent);

-		}

-		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);

+	public static int getHitCount(IMarker marker) {

+		JavaBreakpoint breakpoint= getBreakpoint(marker);

+		if (breakpoint instanceof LineBreakpoint) {

+			return ((LineBreakpoint)breakpoint).getHitCount();

+		}

+		return -1;

 	}

 	

 	/**

@@ -440,54 +162,14 @@
 	 * @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;

+	public static void setHitCount(IMarker marker, int hitCount) throws CoreException {

+		JavaBreakpoint breakpoint= getBreakpoint(marker);

+		if (breakpoint instanceof LineBreakpoint) {

+			((LineBreakpoint) breakpoint).setHitCount(hitCount);

 		}

 	}

-	/**

-	 * 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 field handle identifier of the given breakpoint

-	 */

-	public static String getFieldHandleIdentifier(IMarker breakpoint) {

-		return DebugJavaUtils.getFieldHandleIdentifier(breakpoint);

-	}

-	

-	/**

-	 * Returns the field the given breakpoint is installed on

-	 * or <code>null</code> if breakpoint is not installed in a method.

-	 * 

-	 * @param breakpoint the breakpoint

-	 * @return a field or <code>null</code>

-	 */

-	public static IField getField(IMarker breakpoint) {

-		return DebugJavaUtils.getField(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

@@ -497,118 +179,27 @@
 	 * @param breakpoint the breakpoint

 	 * @return a type, or <code>nulll</code>

 	 */

-	public static IType getType(IMarker breakpoint) {

-		return DebugJavaUtils.getType(breakpoint);

+	public static IType getType(IMarker marker) {

+		JavaBreakpoint breakpoint= getBreakpoint(marker);

+		if (breakpoint != null) {

+			return breakpoint.getBreakpointType();

+		}

+		return null;

 	}

+

 	/**

-	 * 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

+	 * Returns the JavaBreakpoint in the breakpoint manager associated

+	 * with the given marker. If no such breakpoint exists, returns 

+	 * <code>null</code>.

 	 */

-	public static boolean isCaught(IMarker breakpoint) {

-		return DebugJavaUtils.isCaught(breakpoint);

+	private static JavaBreakpoint getBreakpoint(IMarker marker) {

+		IBreakpoint breakpoint= getBreakpointManager().getBreakpoint(marker);

+		if (breakpoint instanceof JavaBreakpoint) {

+			return (JavaBreakpoint) breakpoint;

+		}

+		return null;

 	}

-	/**

-	 * 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 watchpoint.

-	 *

-	 * @param breakpoint the breakpoint

-	 * @return whether the given breakpoint is a watchpoint

-	 */

-	public static boolean isWatchpoint(IMarker breakpoint) {

-		return DebugJavaUtils.isWatchpoint(breakpoint);

-	}

-	

-	/**

-	 * Returns whether the given breakpoint

-	 * is an access watchpoint.

-	 * 

-	 * @param breakpoint the breakpoint

-	 * @return whether the given breakpoint 

-	 * is an access watchpoint

-	 */

-	public static boolean isAccess(IMarker breakpoint) {

-		return DebugJavaUtils.isAccess(breakpoint);

-	}

-	

-	/**

-	 * Returns whether the given breakpoint

-	 * is an modificaion watchpoint.

-	 * 

-	 * @param breakpoint the breakpoint

-	 * @return whether the given breakpoint 

-	 * is an modification watchpoint

-	 */

-	public static boolean isModification(IMarker breakpoint) {

-		return DebugJavaUtils.isModification(breakpoint);

-	}	

-	

-	public static boolean isAutoDisabled(IMarker breakpoint) {

-		return DebugJavaUtils.isAutoDisabled(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);

-	}

+

 }

 

 

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/DebugJavaResources.properties b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/DebugJavaResources.properties
index 5bf68e7..d98730d 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/DebugJavaResources.properties
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/DebugJavaResources.properties
@@ -12,6 +12,25 @@
 jdi.common.couldnt_set_breakpoint=Breakpoint could not be set at or near line number {0}
 
 ##############################################################
+# Breakpoint / Marker
+##############################################################
+jdi_marker.label.line=line:
+jdi_marker.label.hitCount=hit count:
+
+jdi_marker.label.exception.format={1}: {0} 
+jdi_marker.label.exception.caught=caught
+jdi_marker.label.exception.uncaught=uncaught
+jdi_marker.label.exception.both=caught and uncaught
+
+jdi_marker.label.watchpoint.format={1}: {0} 
+jdi_marker.label.watchpoint.access=access
+jdi_marker.label.watchpoint.modification=modification
+jdi_marker.label.watchpoint.both=access and modification
+
+jdi_breakpoint.error.access_watchpoint.not_supported=VM does not support access watchpoints.
+jdi_breakpoint.error.modification_watchpoint.not_supported=VM does not support modification watchpoints.
+
+##############################################################
 # JDIDebugTarget
 ##############################################################
 
@@ -26,8 +45,6 @@
 jdi_debug_target.error.resume.not_supported=VM does not support resume.
 jdi_debug_target.error.suspend.not_supported=VM does not support suspend.
 jdi_debug_target.error.terminate.not_supported=VM does not support termination.
-jdi_debug_target.error.access_watchpoint.not_supported=VM does not support access watchpoints.
-jdi_debug_target.error.modification_watchpoint.not_supported=VM does not support modification watchpoints.
 jdi_debug_target.error.terminate.exception=Exception occurred while terminating VM.

 jdi_debug_target.error.get_crc=Exception occurred retrieving CRC
 
@@ -76,6 +93,18 @@
 jdi_thread.error.no_built_state=Project must be built to perform evaluations
 jdi_thread.error.invalid_evaluation_location=Unable to perform evaluation at current location. Thread must be suspended by a breakpoint or step.
 
+jdi_thread.label.exception_sys=System Thread [{0}] (Suspended (exception {1}))
+jdi_thread.label.exception_usr=Thread [{0}] (Suspended (exception {1}))
+jdi_thread.label.line_breakpoint_sys=System Thread [{0}] (Suspended (breakpoint at line {1} in {2}))
+jdi_thread.label.line_breakpoint_usr=Thread [{0}] (Suspended (breakpoint at line {1} in {2}))
+jdi_thread.label.run_to_line_breakpoint_usr=Thread [{0}] (Suspended (run to line line {1} in {2}))
+jdi_thread.label.run_to_line_breakpoint_sys=System Thread [{0}] (Suspended (run to line line {1} in {2}))
+jdi_thread.label.access_sys=System Thread [{0}] (Suspended (access of field {1} in {2}))
+jdi_thread.label.access_usr=Thread [{0}] (Suspended (access of field {1} in {2}))
+jdi_thread.label.modification_sys=System Thread [{0}] (Suspended (modification of field {1} in {2}))
+jdi_thread.label.modification_usr=Thread [{0}] (Suspended (modification of field {1} in {2}))
+jdi_thread.label.run_to_line_sys=System Thread [{0}] (Suspended (run to line {1} in {2}))
+jdi_thread.label.run_to_line_usr=Thread [{0}] (Suspended (run to line {1} in {2}))
 
 ##############################################################
 # JDIStackFrame
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/DebugJavaUtils.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/DebugJavaUtils.java
index 102f95b..0dae17f 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/DebugJavaUtils.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/DebugJavaUtils.java
Binary files differ
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/EventDispatcher.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/EventDispatcher.java
index 4af40a4..064469e 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/EventDispatcher.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/EventDispatcher.java
@@ -10,9 +10,26 @@
 import org.eclipse.core.resources.ResourcesPlugin;

 import org.eclipse.core.runtime.CoreException;

 import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.debug.core.IDebugConstants;

+

 import com.sun.jdi.ThreadReference;

 import com.sun.jdi.VMDisconnectedException;

-import com.sun.jdi.event.*;

+import com.sun.jdi.event.BreakpointEvent;

+import com.sun.jdi.event.ClassPrepareEvent;

+import com.sun.jdi.event.Event;

+import com.sun.jdi.event.EventIterator;

+import com.sun.jdi.event.EventQueue;

+import com.sun.jdi.event.EventSet;

+import com.sun.jdi.event.ExceptionEvent;

+import com.sun.jdi.event.LocatableEvent;

+import com.sun.jdi.event.MethodEntryEvent;

+import com.sun.jdi.event.StepEvent;

+import com.sun.jdi.event.ThreadDeathEvent;

+import com.sun.jdi.event.ThreadStartEvent;

+import com.sun.jdi.event.VMDeathEvent;

+import com.sun.jdi.event.VMDisconnectEvent;

+import com.sun.jdi.event.VMStartEvent;

+import com.sun.jdi.event.WatchpointEvent;

 

 /**

  * Dispatches events generated by a debuggable VM.

@@ -61,71 +78,45 @@
 			if (event instanceof StepEvent) {

 				dispatchStepEvent((StepEvent)event);

 			} else

-				if (event instanceof BreakpointEvent) {

-					dispatchLocatableEvent((LocatableEvent) event);

+				if ((event instanceof BreakpointEvent) ||

+				(event instanceof LocatableEvent) ||

+				(event instanceof ExceptionEvent) ||

+				(event instanceof WatchpointEvent) ||

+				(event instanceof MethodEntryEvent)) {

+					dispatchBreakpointEvent(event);

 				} else

-					if (event instanceof ExceptionEvent) {

-						dispatchExceptionEvent((ExceptionEvent) event);

+					if (event instanceof ThreadStartEvent) {

+						fTarget.handleThreadStart((ThreadStartEvent) event);

 					} else

-						if (event instanceof ThreadStartEvent) {

-							fTarget.handleThreadStart((ThreadStartEvent) event);

+						if (event instanceof ThreadDeathEvent) {

+							fTarget.handleThreadDeath((ThreadDeathEvent) event);

 						} else

-							if (event instanceof ThreadDeathEvent) {

-								fTarget.handleThreadDeath((ThreadDeathEvent) event);

+							if (event instanceof ClassPrepareEvent) {

+								fTarget.handleClassLoad((ClassPrepareEvent) event);

 							} else

-								if (event instanceof ClassPrepareEvent) {

-									fTarget.handleClassLoad((ClassPrepareEvent) event);

+								if (event instanceof VMDeathEvent) {

+									fTarget.handleVMDeath((VMDeathEvent) event);

+									fKeepReading= false; // stop listening for events

 								} else

-									if (event instanceof WatchpointEvent) {

-										dispatchLocatableEvent((LocatableEvent) event);

-									} else

-										if (event instanceof MethodEntryEvent) {

-											fTarget.handleMethodEntry((MethodEntryEvent) event);

-										} else

-											if (event instanceof VMDeathEvent) {

-												fTarget.handleVMDeath((VMDeathEvent) event);

-												fKeepReading= false; // stop listening for events

-											} else

-												if (event instanceof VMDisconnectEvent) {

-													fTarget.handleVMDisconnect((VMDisconnectEvent) event);

-													fKeepReading= false; // stop listening for events

-												} else if (event instanceof VMStartEvent) {

-													fTarget.handleVMStart((VMStartEvent)event);

-												} else {

-													// Unknown Event Type

-												}

+									if (event instanceof VMDisconnectEvent) {

+										fTarget.handleVMDisconnect((VMDisconnectEvent) event);

+										fKeepReading= false; // stop listening for events

+									} else if (event instanceof VMStartEvent) {

+										fTarget.handleVMStart((VMStartEvent)event);

+									} else {

+										// Unknown Event Type

+									}

 		}

 	}

-

-	protected void dispatchLocatableEvent(LocatableEvent event) {

+	

+	protected void dispatchBreakpointEvent(Event event) {

 		if (!fKeepReading) {

 			return;

 		}

-		ThreadReference threadRef= event.thread();

-		JDIThread thread= findThread(threadRef);

-		if (thread == null) {

-			fTarget.resume(threadRef);

-			return;

-		} else {

-			thread.handleLocatableEvent(event);

-		}

+		JavaBreakpoint breakpoint= (JavaBreakpoint)event.request().getProperty(IDebugConstants.BREAKPOINT);

+		breakpoint.handleEvent(event, fTarget);		

 	}

 

-	protected void dispatchExceptionEvent(ExceptionEvent event) {

-		if (!fKeepReading) {

-			return;

-		}

-		ThreadReference threadRef= event.thread();

-		JDIThread thread= findThread(threadRef);

-		if (thread == null) {

-			fTarget.resume(threadRef);

-			return;

-		} else {

-			thread.handleException((ExceptionEvent) event);

-		}

-	}

-

-

 	protected void dispatchStepEvent(StepEvent event) {

 		ThreadReference threadRef= event.thread();

 		JDIThread thread= findThread(threadRef);

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/ExceptionBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/ExceptionBreakpoint.java
new file mode 100644
index 0000000..b8aa7ad
--- /dev/null
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/ExceptionBreakpoint.java
@@ -0,0 +1,368 @@
+package org.eclipse.jdt.internal.debug.core;

+

+import java.text.MessageFormat;

+import java.util.List;

+import java.util.Map;

+

+import org.eclipse.core.resources.*;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.debug.core.DebugException;

+import org.eclipse.debug.core.IDebugConstants;

+import org.eclipse.jdt.core.IType;

+import org.eclipse.jdt.core.JavaCore;

+import org.eclipse.jdt.debug.core.IJavaDebugConstants;

+

+import com.sun.jdi.*;

+import com.sun.jdi.event.Event;

+import com.sun.jdi.event.ExceptionEvent;

+import com.sun.jdi.request.EventRequest;

+import com.sun.jdi.request.ExceptionRequest;

+

+public class ExceptionBreakpoint extends JavaBreakpoint  {

+	

+	// Thread label String keys

+	private static final String EXCEPTION_SYS= THREAD_LABEL + "exception_sys";

+	private static final String EXCEPTION_USR= THREAD_LABEL + "exception_usr";

+	// Marker label String keys

+	protected final static String EXCEPTION= MARKER_LABEL + "exception.";

+	protected final static String FORMAT= EXCEPTION + "format";

+	protected final static String CAUGHT= EXCEPTION + "caught";

+	protected final static String UNCAUGHT= EXCEPTION + "uncaught";

+	protected final static String BOTH= EXCEPTION + "both";	

+	// Attribute strings

+	protected static final String[] fgExceptionBreakpointAttributes= new String[]{IJavaDebugConstants.CHECKED, IJavaDebugConstants.TYPE_HANDLE};	

+	

+	static String fMarkerType= IJavaDebugConstants.JAVA_EXCEPTION_BREAKPOINT;	

+	

+	public ExceptionBreakpoint(IMarker marker) {

+		super(marker);

+	}

+	

+	/**

+	 * 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 ExceptionBreakpoint(final IType exception, final boolean caught, final boolean uncaught, final boolean checked) throws DebugException {

+		IWorkspaceRunnable wr= new IWorkspaceRunnable() {

+

+			public void run(IProgressMonitor monitor) throws CoreException {

+				IResource resource= null;

+				resource= exception.getUnderlyingResource();

+

+				if (resource == null) {

+					resource= exception.getJavaProject().getProject();

+				}

+				

+				// create the marker

+				fMarker= resource.createMarker(fMarkerType);

+				// configure the standard attributes

+				configure(getPluginIdentifier(), true);

+				// configure caught, uncaught, checked, and the type attributes

+				setDefaultCaughtAndUncaught();

+				configureExceptionBreakpoint(checked, exception);

+

+				// configure the marker as a Java marker

+				Map attributes= getAttributes();

+				JavaCore.addJavaElementMarkerAttributes(attributes, exception);

+				setAttributes(attributes);

+			}

+

+		};

+		run(wr);

+	}

+	

+	/**

+	 * Sets the <code>CAUGHT</code>, <code>UNCAUGHT</code>, <code>CHECKED</code> and 

+	 * <code>TYPE_HANDLE</code> attributes of the given exception breakpoint.

+	 */

+	public void configureExceptionBreakpoint(boolean checked, IType exception) throws CoreException {

+		String handle = exception.getHandleIdentifier();

+		Object[] values= new Object[]{new Boolean(checked), handle};

+		setAttributes(fgExceptionBreakpointAttributes, values);

+	}	

+	

+	public void setDefaultCaughtAndUncaught() {

+		Object[] values= new Object[]{Boolean.TRUE, Boolean.TRUE};

+		String[] attributes= new String[]{IJavaDebugConstants.CAUGHT, IJavaDebugConstants.UNCAUGHT};

+		try {

+			setAttributes(attributes, values);

+		} catch (CoreException ce) {

+			logError(ce);

+		}		

+	}

+	

+	/**

+	 * @see JavaBreakpoint#installIn(JDIDebugTarget)

+	 */

+	public void addToTarget(JDIDebugTarget target) {

+		fTarget= target;

+		changeForTarget(target);

+	}	

+	

+	/**

+	 * An exception breakpoint has changed

+	 */

+	public void changeForTarget(JDIDebugTarget target) {

+

+		boolean caught= isCaught();

+		boolean uncaught= isUncaught();

+

+		if (caught || uncaught) {

+			IType exceptionType = getBreakpointType();

+			if (exceptionType == null) {

+//				internalError(ERROR_BREAKPOINT_NO_TYPE);

+				return;

+			}

+			String exceptionName = exceptionType.getFullyQualifiedName();

+			String topLevelName = getTopLevelTypeName();

+			if (topLevelName == null) {

+//				internalError(ERROR_BREAKPOINT_NO_TYPE);

+				return;

+			}

+			List classes= target.jdiClassesByName(exceptionName);

+			ReferenceType exClass= null;

+			if (classes != null && !classes.isEmpty()) {

+				exClass= (ReferenceType) classes.get(0);

+			}

+			if (exClass == null) {

+				// defer the exception

+				target.defer(this, topLevelName);

+			} else {

+				// new or changed - first delete the old request

+				if (null != target.getRequest(this))

+					removeFromTarget(target);

+				ExceptionRequest request= null;

+				try {

+					request= target.getEventRequestManager().createExceptionRequest(exClass, caught, uncaught);

+					request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);

+					request.putProperty(IDebugConstants.BREAKPOINT, this);

+				} catch (VMDisconnectedException e) {

+					return;

+				} catch (RuntimeException e) {

+					logError(e);

+					return;

+				}

+				request.setEnabled(isEnabled());

+				target.installBreakpoint(this, request);

+			}

+		} else {

+			removeFromTarget(target);

+		}

+	}

+

+	/**

+	 * An exception breakpoint has been removed

+	 */

+	public void removeFromTarget(JDIDebugTarget target) {

+		IType type = getBreakpointType();

+		if (type == null) {

+//			internalError(ERROR_BREAKPOINT_NO_TYPE);

+			return;

+		}

+		String name = type.getFullyQualifiedName();

+		ExceptionRequest request= (ExceptionRequest) target.uninstallBreakpoint(this);

+		if (request != null) {

+			try {

+				target.getEventRequestManager().deleteEventRequest(request);

+			} catch (VMDisconnectedException e) {

+				return;

+			} catch (RuntimeException e) {

+				logError(e);

+				return;

+			}

+		}

+		List deferred = target.getDeferredBreakpointsByClass(name);

+		if (deferred != null)  {

+			deferred.remove(this);

+			if (deferred.isEmpty()) {

+				target.removeDeferredBreakpointByClass(name);

+			}

+		}

+	}		

+	

+	/**

+	 * @see JavaBreakpoint#handleEvent(Event)

+	 */

+	public void handleEvent(Event event, JDIDebugTarget target){

+		if (!(event instanceof ExceptionEvent)) {

+			return;

+		}

+		ThreadReference threadRef= ((ExceptionEvent)event).thread();

+		JDIThread thread= target.findThread(threadRef);

+		if (thread == null) {

+			target.resume(threadRef);

+			return;

+		} else {

+			thread.handleSuspendForBreakpoint(this);

+		}

+	}

+	

+	/**

+	 * @see JavaBreakpoint#isSupportedBy(VirtualMachine)

+	 */

+	public boolean isSupportedBy(VirtualMachine vm) {

+		return true;

+	}

+	

+	/**

+	 * Enable this exception breakpoint.

+	 * 

+	 * If the exception breakpoint is not catching caught or uncaught,

+	 * set the default values. If this isn't done, the resulting

+	 * state (enabled with caught and uncaught both disabled)

+	 * is ambiguous.

+	 */

+	public void enable() {

+		if (!(isCaught() || isUncaught())) {

+			setDefaultCaughtAndUncaught();

+		}

+		super.enable();

+	}	

+	

+	/**

+	 * Toggle the caught state of this breakpoint

+	 */

+	public void toggleCaught() throws CoreException {

+		setCaught(!isCaught());

+	}

+	

+	/**

+	 * Returns the <code>CAUGHT</code> attribute of the given breakpoint

+	 * or <code>false</code> if the attribute is not set.

+	 */

+	public boolean isCaught() {

+		return getBooleanAttribute(IJavaDebugConstants.CAUGHT);

+	}

+	

+	/**

+	 * Sets the <code>CAUGHT</code> attribute of the given breakpoint.

+	 */

+	public void setCaught(boolean caught) throws CoreException {

+		if (caught == isCaught()) {

+			return;

+		}

+		try {

+			setBooleanAttribute(IJavaDebugConstants.CAUGHT, caught);

+			if (caught && !isEnabled()) {

+				enable();

+			} else if (!(caught || isUncaught())) {

+				disable();

+			}

+		} catch (CoreException ce) {

+			logError(ce);

+		}

+		if (fTarget != null) {

+			// Notify the target that this watchpoint has changed

+			changeForTarget(fTarget);

+		}				

+	}

+	

+	/**

+	 * Toggle the caught state of this breakpoint

+	 */

+	public void toggleUncaught() throws CoreException {

+		setUncaught(!isUncaught());

+	}	

+	

+	/**

+	 * Returns the <code>UNCAUGHT</code> attribute of the given breakpoint

+	 * or <code>false</code> if the attribute is not set.

+	 */

+	public boolean isUncaught() {

+		return getBooleanAttribute(IJavaDebugConstants.UNCAUGHT);

+	}	

+	

+	/**

+	 * Sets the <code>UNCAUGHT</code> attribute of the given breakpoint.

+	 */

+	public void setUncaught(boolean uncaught) throws CoreException {

+	

+		if (uncaught == isUncaught()) {

+			return;

+		}

+		try {

+			setBooleanAttribute(IJavaDebugConstants.UNCAUGHT, uncaught);

+			if (uncaught && !isEnabled()) {

+				enable();

+			} else if (!(uncaught || isCaught())) {

+				disable();

+			}

+		} catch (CoreException ce) {

+			logError(ce);

+		}

+		if (fTarget != null) {

+			// Notify the target that this watchpoint has changed

+			changeForTarget(fTarget);

+		}				

+	}

+	

+	/**

+	 * Returns whether the given breakpoint represents a checked exception.

+	 */

+	public boolean isChecked() {

+		return getBooleanAttribute(IJavaDebugConstants.CHECKED);

+	}

+	

+	/**

+	 * Sets the <code>CHECKED</code> attribute of the given breakpoint.

+	 */

+	public void setChecked(boolean checked) throws CoreException {

+		setBooleanAttribute(IJavaDebugConstants.CHECKED, checked);	

+	}	

+	

+	/**

+	 * @see JavaBreakpoint

+	 */	

+	public String getFormattedThreadText(String threadName, String typeName, boolean systemThread) {

+		if (systemThread) {

+			return getFormattedString(EXCEPTION_SYS, new String[] {threadName, typeName});

+		}

+		return getFormattedString(EXCEPTION_USR, new String[] {threadName, typeName});		

+	}

+	

+	/**

+	 */

+	public String getMarkerText(boolean showQualified) {

+		String name;

+		if (showQualified) {

+			name= getBreakpointType().getFullyQualifiedName();

+		} else {

+			name= getBreakpointType().getElementName();

+		}

+

+		String state= null;

+		boolean c= isCaught();

+		boolean u= isUncaught();

+		if (c && u) {

+			state= BOTH;

+		} else if (c) {

+			state= CAUGHT;

+		} else if (u) {

+			state= UNCAUGHT;

+		}

+		String label= null;

+		if (state == null) {

+			label= name;

+		} else {

+			String format= DebugJavaUtils.getResourceString(FORMAT);

+			state= DebugJavaUtils.getResourceString(state);

+			label= MessageFormat.format(format, new Object[] {state, name});

+		}

+		return label;	

+	}

+

+}

+

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java
index 7517235..f16e0c9 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugPlugin.java
@@ -5,14 +5,10 @@
  * All Rights Reserved.

  */

 

-import org.eclipse.debug.core.DebugPlugin;

-import org.eclipse.debug.core.IDebugConstants;

-import org.eclipse.debug.core.ILaunchManager;

-import org.eclipse.debug.core.model.IDebugTarget;

 import org.eclipse.core.resources.*;

-import org.eclipse.core.runtime.CoreException;

-import org.eclipse.core.runtime.IPluginDescriptor;

-import org.eclipse.core.runtime.Plugin;

+import org.eclipse.core.runtime.*;

+import org.eclipse.debug.core.*;

+import org.eclipse.debug.core.model.IDebugTarget;

 import org.eclipse.jdt.debug.core.IJavaDebugConstants;

 

 /**

@@ -44,24 +40,26 @@
 	public void startup() throws CoreException {

 		

 		fJavaHCRMgr= new JavaHotCodeReplaceManager();

-		fJavaHCRMgr.startup();		

+		fJavaHCRMgr.startup();	

 

-		IMarker[] breakpoints= null;

+		IMarker[] markers= null;

 		IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();

 		try {

-			breakpoints= root.findMarkers(IJavaDebugConstants.JAVA_LINE_BREAKPOINT, true, IResource.DEPTH_INFINITE);

+			markers= root.findMarkers(IJavaDebugConstants.JAVA_LINE_BREAKPOINT, true, IResource.DEPTH_INFINITE);

 		} catch (CoreException e) {

 			DebugJavaUtils.logError(e);

 			return;

 		}

-		

-		if (breakpoints == null) {

+		if (markers == null) {

 			return;

 		}

-		

-		for (int i = 0; i < breakpoints.length; i++) {

-			IMarker breakpoint = breakpoints[i];

-			DebugJavaUtils.configureBreakpointAtStartup(breakpoint);

+

+		IBreakpointManager manager= DebugPlugin.getDefault().getBreakpointManager();

+		for (int i= 0; i < markers.length; i++) {

+			JavaBreakpoint breakpoint= (JavaBreakpoint)manager.loadMarker(markers[i]);

+			if (breakpoint != null) {

+				breakpoint.configureBreakpointAtStartup();

+			}

 		}

 	}

 

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugTarget.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugTarget.java
index 9e4fab3..9b1ad20 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugTarget.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIDebugTarget.java
@@ -5,21 +5,20 @@
  * All Rights Reserved.

  */

 

-import com.sun.jdi.*;

+import java.io.ByteArrayInputStream;

+import java.util.*;

+

 import org.eclipse.core.resources.*;

 import org.eclipse.core.runtime.*;

 import org.eclipse.debug.core.*;

 import org.eclipse.debug.core.model.*;

 import org.eclipse.jdt.core.*;

 import org.eclipse.jdt.core.eval.IEvaluationContext;

-import org.eclipse.jdt.debug.core.IJavaDebugConstants;

-import org.eclipse.jdt.debug.core.IJavaDebugTarget;

-import org.eclipse.jdt.debug.core.JDIDebugModel;

+import org.eclipse.jdt.debug.core.*;

+

+import com.sun.jdi.*;

 import com.sun.jdi.event.*;

 import com.sun.jdi.request.*;

-import java.io.ByteArrayInputStream;

-import java.text.MessageFormat;

-import java.util.*;

 

 /**

  * Debug target for JDI debug model.

@@ -41,25 +40,12 @@
 	private final static String ERROR_RESUME_NOT_SUPPORTED = ERROR + "resume.not_supported";

 	private final static String ERROR_SUSPEND_NOT_SUPPORTED = ERROR + "suspend.not_supported";

 	private final static String ERROR_TERMINATE_NOT_SUPPORTED = ERROR + "terminate.not_supported";

-	private final static String ERROR_ACCESS_WATCHPOINT_NOT_SUPPORTED = ERROR + "access.not_supported";

-	private final static String ERROR_MODIFICATION_WATCHPOINT_NOT_SUPPORTED = ERROR + "modification.net_supported";

 	private final static String ERROR_TERMINATE = ERROR + "terminate.exception";

 	private static final String ERROR_GET_CRC= ERROR + "get_crc";

 	

 	private static final int MAX_THREAD_DEATH_ATTEMPTS = 1;

 	

 	/**

-	 * Key used to store the class name attribute pertinent to a

-	 * specific method entry request. Used for method entry breakpoints.

-	 */

-	protected final static String CLASS_NAME= "className";

-	/**

-	 * Key used to store the name and signature

-	 * attribute pertinent to a specific method 

-	 * entry request breakpoint. Used for method entry breakpoints.

-	 */

-	protected final static String BREAKPOINT_INFO= "breakpointInfo";

-	/**

 	 * Associated system process, or <code>null</code> if not available.

 	 */

 	protected IProcess fProcess;

@@ -84,8 +70,8 @@
 	 * corresponding class is not yet loaded). 

 	 * <p>

 	 * Key: the fully qualified name of the class

-	 * Value: a <code>List</code> of <code>IMarker</code>s representing the

-	 * deferred breakpointsin that class.

+	 * Value: a <code>List</code> of <code>JavaBreakpoint</code>s representing the

+	 * deferred breakpoints in that class.

 	 */

 	protected Map fDeferredBreakpointsByClass;

 	/**

@@ -98,9 +84,8 @@
 	/**

 	 * Table of installed breakpoints

 	 * <p>

-	 * Key: breakpoint (<code>IMarker</code>)

-	 * Value: the event request associated with the breakpoint (one

-	 * of <code>BreakpointRequest</code> or <code>MethodEntryRequest</code>).

+	 * Key: breakpoint (<code>JavaBreakpoint</code>)

+	 * Value: the event request associated with the breakpoint (<code>Object</code>).

 	 */

 	protected HashMap fInstalledBreakpoints;

 		

@@ -263,9 +248,11 @@
 	 * Installs all breakpoints that currently exist in the breakpoint manager

 	 */

 	protected void initializeBreakpoints() {

-		IMarker[] bps = getBreakpointManager().getBreakpoints(JDIDebugModel.getPluginIdentifier());

+		IBreakpoint[] bps = (IBreakpoint[]) getBreakpointManager().getBreakpoints(JDIDebugModel.getPluginIdentifier());

 		for (int i = 0; i < bps.length; i++) {

-			breakpointAdded(bps[i]);

+			if (bps[i] instanceof JavaBreakpoint) {

+				breakpointAdded((JavaBreakpoint)bps[i]);

+			}

 		}

 	}

 	

@@ -403,7 +390,7 @@
 	 * @param breakpoint the breakpoint to defer

 	 * @param typeName name of the type the given breakpoint is associated with

 	 */

-	protected void defer(IMarker breakpoint, String typeName) {

+	protected void defer(JavaBreakpoint breakpoint, String typeName) {

 		List bps= (List) fDeferredBreakpointsByClass.get(typeName);

 		if (bps == null) {

 			// listen for the load of the type

@@ -595,99 +582,6 @@
 		createThreadDeathInstance(threadRef);

 		resume(threadRef);

 	}

-

-	/**

-	 * Handles a method entry event. If this method entry event is

-	 * in a method that a method entry breakpoint has been set for,

-	 * handle the event as a breakpoint.

-	 */

-	protected void handleMethodEntry(MethodEntryEvent event) {

-		Method enteredMethod = event.method();

-		MethodEntryRequest request = (MethodEntryRequest)event.request();

-		List breakpoints = (List)request.getProperty(IDebugConstants.BREAKPOINT_MARKER);

-		Iterator requestBreakpoints= breakpoints.iterator();

-		IMarker breakpoint= null;

-		int index= 0;

-		while (requestBreakpoints.hasNext()) {

-			IMarker aBreakpoint= (IMarker)requestBreakpoints.next();

-			Object[] nameSignature= getMethodEntryBreakpointInfo(request, aBreakpoint, index);

-			String enteredMethodName= enteredMethod.name();

-			if (nameSignature != null && nameSignature[0].equals(enteredMethodName) &&

-				nameSignature[1].equals(enteredMethod.signature())) {

-				breakpoint= aBreakpoint;

-				break;

-			}

-			index++;	

-		}

-		if (breakpoint == null) {

-			handleMethodEntryResume(event.thread());

-			return;

-		}	

-		

-		List counts = (List)request.getProperty(IJavaDebugConstants.HIT_COUNT);

-		Integer count= (Integer)counts.get(index);

-		if (count != null) {

-			handleHitCountMethodEntryBreakpoint(event, breakpoint, counts, count, index);

-		} else {

-			// no hit count - suspend

-			handleMethodEntryBreakpoint(event.thread(), breakpoint);

-		}

-	}

-	

-	protected void handleMethodEntryResume(ThreadReference thread) {

-		if (!hasPendingEvents()) {

-			resume(thread);

-		}

-	}

-	

-	protected void handleHitCountMethodEntryBreakpoint(MethodEntryEvent event, IMarker breakpoint, List counts, Integer count, int index) {

-	// decrement count and suspend if 0

-		int hitCount = count.intValue();

-		if (hitCount > 0) {

-			hitCount--;

-			count = new Integer(hitCount);

-			counts.set(index, count);

-			if (hitCount == 0) {

-				// the count has reached 0, breakpoint hit

-				handleMethodEntryBreakpoint(event.thread(), breakpoint);

-				try {

-					// make a note that we auto-disabled the breakpoint

-					// order is important here...see methodEntryChanged

-					DebugJavaUtils.setExpired(breakpoint, true);

-					getBreakpointManager().setEnabled(breakpoint, false);

-				} catch (CoreException e) {

-					internalError(e);

-				}

-			}  else {

-				// count still > 0, keep running

-				handleMethodEntryResume(event.thread());		

-			}

-		} else {

-			// hit count expired, keep running

-			handleMethodEntryResume(event.thread());

-		}

-	}

-	protected String[] getMethodEntryBreakpointInfo(MethodEntryRequest request, IMarker breakpoint, int index) {

-		List nameSignatures = (List)request.getProperty(BREAKPOINT_INFO);

-		if (nameSignatures.get(index) != null) {

-			return (String[])nameSignatures.get(index);

-		}

-		String[] nameSignature= new String[2];

-		IMethod aMethod= DebugJavaUtils.getMethod(breakpoint); 

-			try {

-				if (aMethod.isConstructor()) {

-					nameSignature[0]= "<init>";

-				} else {

-					 nameSignature[0]= aMethod.getElementName();

-				}

-				nameSignature[1]= aMethod.getSignature();

-				nameSignatures.add(index, nameSignature);

-				return nameSignature;

-			} catch (JavaModelException e) {

-				logError(e);

-				return null;

-			}

-	}

 	

 	/**

 	 * Resumes the given thread

@@ -701,9 +595,9 @@
 		}

 	}

 	 

-	protected void handleMethodEntryBreakpoint(ThreadReference thread, IMarker breakpoint) {

+	protected void handleMethodEntryBreakpoint(ThreadReference thread, JavaBreakpoint breakpoint) {

 		JDIThread jdiThread = findThread(thread);

-		jdiThread.handleSuspendMethodEntry(breakpoint);

+		jdiThread.handleSuspendForBreakpoint(breakpoint);

 	}

 	/**

 	 * Handles a thread death event.

@@ -742,107 +636,51 @@
 		terminate0();

 	}	

 	

-	/**

-	 * Returns the top-level type name associated with the type 

-	 * the given breakpoint is associated with, or <code>null</code>.

-	 */

-	protected String getTopLevelTypeName(IMarker breakpoint) {

-		IType type = DebugJavaUtils.getType(breakpoint);

-		if (type != null) {

-			while (type.getDeclaringType() != null) {

-				type = type.getDeclaringType();

-			}

-			return type.getFullyQualifiedName();

-		}

-		return null;

-	}

-	

+

 	/**

 	 * Installs or defers the given breakpoint

 	 */

-	public void breakpointAdded(IMarker breakpoint) {

-		if (DebugJavaUtils.isExceptionBreakpoint(breakpoint)) {

-			exceptionBreakpointAdded(breakpoint);

-		} else if (DebugJavaUtils.isMethodEntryBreakpoint(breakpoint)) {

-			methodEntryBreakpointAdded(breakpoint);

-		} else if (DebugJavaUtils.isWatchpoint(breakpoint)) {

-			watchpointAdded(breakpoint);

-		} else {

-			lineBreakpointAdded(breakpoint);

-		}

+	public void breakpointAdded(IBreakpoint breakpoint) {

+		breakpoint.addToTarget(this);

 	}

 	

-	protected void lineBreakpointAdded(IMarker breakpoint) {

-		String topLevelName= getTopLevelTypeName(breakpoint);

-		if (topLevelName == null) {

-			internalError(ERROR_BREAKPOINT_NO_TYPE);

-			return;

-		}

-		

-		// look for the top-level class - if it is loaded, inner classes may also be loaded

-		List classes= jdiClassesByName(topLevelName);

-		if (classes == null || classes.isEmpty()) {

-			// defer

-			defer(breakpoint, topLevelName);

-		} else {

-			// try to install

-			ReferenceType type= (ReferenceType) classes.get(0);

-			if (!installLineBreakpoint(breakpoint, type)) {

-				// install did not succeed - could be an inner type not yet loaded

-				defer(breakpoint, topLevelName);

-			}

-		}

+	/**

+	 * Add a breakpoint to the installed breakpoints collection

+	 */

+	public void installBreakpoint(JavaBreakpoint breakpoint, Object request) {

+		fInstalledBreakpoints.put(breakpoint, request);

 	}

 

 	/**

-	 * Installs a line breakpoint in the given type, returning whether successful.

+	 * Remove a breakpoint from the installed breakpoints collection

 	 */

-	protected boolean installLineBreakpoint(IMarker marker, ReferenceType type) {

-		Location location= null;

-		IBreakpointManager manager= getBreakpointManager();

-		int lineNumber= manager.getLineNumber(marker);			

-		location= determineLocation(lineNumber, type);

-		if (location == null) {

-			// could be an inner type not yet loaded, or line information not available

-			return false;

-		}

-		

-		if (createLineBreakpointRequest(location, marker) != null) {

-			// update the install attibute on the breakpoint

-			if (!fInHCR) {

-				try {

-					DebugJavaUtils.incrementInstallCount(marker);

-				} catch (CoreException e) {

-					internalError(e);

-				}

-			}

-			return true;

-		} else {

-			return false;

-		}

-		

+	public Object uninstallBreakpoint(JavaBreakpoint breakpoint) {

+		return fInstalledBreakpoints.remove(breakpoint);		

 	}

 	

 	/**

-	 * Creates, installs, and returns a line breakpoint request at

-	 * the given location for the given breakpoint.

+	 * Return the request object associated with the given breakpoint

 	 */

-	protected BreakpointRequest createLineBreakpointRequest(Location location, IMarker breakpoint) {

-		BreakpointRequest request = null;

-		try {

-			request= getEventRequestManager().createBreakpointRequest(location);

-			configureRequest(request, breakpoint);

-		} catch (VMDisconnectedException e) {

-			fInstalledBreakpoints.remove(breakpoint);

-			return null;

-		} catch (RuntimeException e) {

-			fInstalledBreakpoints.remove(breakpoint);

-			internalError(e);

-			return null;

-		}

-		request.setEnabled(getBreakpointManager().isEnabled(breakpoint));

-		fInstalledBreakpoints.put(breakpoint, request);		

-		return request;

+	public Object getRequest(JavaBreakpoint breakpoint) {

+		return fInstalledBreakpoints.get(breakpoint);

+	}

+	

+	/**

+	 * Return the deferred breakpoints

+	 */

+	public List getDeferredBreakpointsByClass(String name) {

+		return (List)fDeferredBreakpointsByClass.get(name);

+	}

+	

+	/**

+	 * Remove a deferred breakpoint

+	 */

+	public void removeDeferredBreakpointByClass(String name) {

+		fDeferredBreakpointsByClass.remove(name);

+	}

+	

+	public boolean inHCR() {

+		return fInHCR;

 	}

 

 	/**

@@ -900,424 +738,8 @@
 	/**

 	 * @see IBreakpointSupport

 	 */

-	public void breakpointChanged(IMarker breakpoint, IMarkerDelta delta) {

-		if (DebugJavaUtils.isExceptionBreakpoint(breakpoint)) {

-			exceptionBreakpointChanged(breakpoint);

-		} else if (DebugJavaUtils.isMethodEntryBreakpoint(breakpoint)) {

-			methodEntryBreakpointChanged(breakpoint, delta);

-		} else if (DebugJavaUtils.isWatchpoint(breakpoint)) {

-			watchpointChanged(breakpoint);

-		} else {

-			lineBreakpointChanged(breakpoint);

-		}

-	}

-	

-	protected void lineBreakpointChanged(IMarker breakpoint) {

-		EventRequest request= (BreakpointRequest) fInstalledBreakpoints.get(breakpoint);

-		if (request != null) {

-			// already installed - could be a change in the enabled state or hit count

-			//may result in a new request being generated

-			request= updateHitCount(request, breakpoint);

-			if (request != null) {

-				updateEnabledState(request, breakpoint);

-				fInstalledBreakpoints.put(breakpoint, request);				

-			}

-		}

-	}

-

-	protected void updateMethodEntryEnabledState(MethodEntryRequest request)  {

-		IBreakpointManager manager= getBreakpointManager();

-		Iterator breakpoints= ((List)request.getProperty(IDebugConstants.BREAKPOINT_MARKER)).iterator();

-		boolean requestEnabled= false;

-		while (breakpoints.hasNext()) {

-			IMarker breakpoint= (IMarker)breakpoints.next();

-			if (manager.isEnabled(breakpoint)) {

-				requestEnabled = true;

-				break;

-			}

-		}

-		updateEnabledState0(request, requestEnabled);

-	}

-	

-	protected void updateEnabledState(EventRequest request, IMarker breakpoint)  {

-		updateEnabledState0(request, getBreakpointManager().isEnabled(breakpoint));

-		

-	}

-	

-	private void updateEnabledState0(EventRequest request, boolean enabled) {

-		if (request.isEnabled() != enabled) {

-			// change the enabled state

-			try {

-				// if the request has expired, and is not a method entry request, do not disable.

-				// BreakpointRequests that have expired cannot be deleted. However method entry 

-				// requests that are expired can be deleted (since we simulate the hit count)

-				if (request instanceof MethodEntryRequest || !isExpired(request)) {

-					request.setEnabled(enabled);

-				}

-			} catch (VMDisconnectedException e) {

-			} catch (RuntimeException e) {

-				internalError(e);

-			}

-		}

-	}

-	

-	/**

-	 * Update the hit count of an <code>EventRequest</code>. Return a new request with

-	 * the appropriate settings.

-	 */

-	protected EventRequest updateHitCount(EventRequest request, IMarker marker) {		

-		

-		// if the hit count has changed, or the request has expired and is being re-enabled,

-		// create a new request

-		if (hasHitCountChanged(marker, request) || (isExpired(request) && getBreakpointManager().isEnabled(marker))) {

-			try {

-				// delete old request

-				//on JDK you cannot delete (disable) an event request that has hit its count filter

-				if (!isExpired(request)) {

-					getEventRequestManager().deleteEventRequest(request); // disable & remove

-				}				

-				if (request instanceof BreakpointRequest) {

-					Location location = ((BreakpointRequest) request).location();

-					request = createLineBreakpointRequest(location, marker);					

-				} else { 

-					Field field= ((WatchpointRequest) request).field();

-					if (request instanceof AccessWatchpointRequest) {

-						request= createAccessWatchpoint(marker, field);

-					} else if (request instanceof ModificationWatchpointRequest) {

-						request= createModificationWatchpoint(marker, field);

-					}

-				}

-			} catch (VMDisconnectedException e) {

-			} catch (RuntimeException e) {

-				internalError(e);

-			}

-		}

-		return request;

-	}

-	

-	/**

-	 * Returns whether the hitCount of a marker is equal to the hitCount of

-	 * the associated request.

-	 */

-	protected boolean hasHitCountChanged(IMarker marker, EventRequest request) {

-		int hitCount= DebugJavaUtils.getHitCount(marker);

-		Integer requestCount= (Integer) request.getProperty(IJavaDebugConstants.HIT_COUNT);

-		int oldCount = -1;

-		if (requestCount != null)  {

-			oldCount = requestCount.intValue();

-		} 

-		return hitCount != oldCount;

-	}

-		

-	/**

-	 * An exception breakpoint has been added.

-	 */

-	protected void exceptionBreakpointAdded(IMarker exceptionBreakpoint) {

-		exceptionBreakpointChanged(exceptionBreakpoint);

-	}

-

-	/**

-	 * An exception breakpoint has changed

-	 */

-	protected void exceptionBreakpointChanged(IMarker exceptionBreakpoint) {

-

-		boolean caught= DebugJavaUtils.isCaught(exceptionBreakpoint);

-		boolean uncaught= DebugJavaUtils.isUncaught(exceptionBreakpoint);

-

-		if (caught || uncaught) {

-			IType exceptionType = DebugJavaUtils.getType(exceptionBreakpoint);

-			if (exceptionType == null) {

-				internalError(ERROR_BREAKPOINT_NO_TYPE);

-				return;

-			}

-			String exceptionName = exceptionType.getFullyQualifiedName();

-			String topLevelName = getTopLevelTypeName(exceptionBreakpoint);

-			if (topLevelName == null) {

-				internalError(ERROR_BREAKPOINT_NO_TYPE);

-				return;

-			}

-			List classes= jdiClassesByName(exceptionName);

-			ReferenceType exClass= null;

-			if (classes != null && !classes.isEmpty()) {

-				exClass= (ReferenceType) classes.get(0);

-			}

-			if (exClass == null) {

-				// defer the exception

-				defer(exceptionBreakpoint, topLevelName);

-			} else {

-				// new or changed - first delete the old request

-				if (null != fInstalledBreakpoints.get(exceptionBreakpoint))

-					exceptionBreakpointRemoved(exceptionBreakpoint);

-				ExceptionRequest request= null;

-				try {

-					request= getEventRequestManager().createExceptionRequest(exClass, caught, uncaught);

-					configureRequest(request, exceptionBreakpoint);

-				} catch (VMDisconnectedException e) {

-					return;

-				} catch (RuntimeException e) {

-					internalError(e);

-					return;

-				}

-				request.setEnabled(getBreakpointManager().isEnabled(exceptionBreakpoint));

-				fInstalledBreakpoints.put(exceptionBreakpoint, request);

-			}

-		} else {

-			exceptionBreakpointRemoved(exceptionBreakpoint);

-		}

-	}

-

-	/**

-	 * An exception breakpoint has been removed

-	 */

-	protected void exceptionBreakpointRemoved(IMarker exceptionBreakpoint) {

-		IType type = DebugJavaUtils.getType(exceptionBreakpoint);

-		if (type == null) {

-			internalError(ERROR_BREAKPOINT_NO_TYPE);

-			return;

-		}

-		String name = type.getFullyQualifiedName();

-		ExceptionRequest request= (ExceptionRequest) fInstalledBreakpoints.remove(exceptionBreakpoint);

-		if (request != null) {

-			try {

-				getEventRequestManager().deleteEventRequest(request);

-			} catch (VMDisconnectedException e) {

-				return;

-			} catch (RuntimeException e) {

-				internalError(e);

-				return;

-			}

-		}

-		List deferred = (List)fDeferredBreakpointsByClass.get(name);

-		if (deferred != null)  {

-			deferred.remove(exceptionBreakpoint);

-			if (deferred.isEmpty()) {

-				fDeferredBreakpointsByClass.remove(name);

-			}

-		}

-	}

-

-	/**

-	 * A watchpoint has been added.

-	 * Create or update the request.

-	 */

-	protected void watchpointAdded(IMarker breakpoint) {

-		selectiveWatchpointAdded(breakpoint, true, true);

-

-	}

-

-	/**

-	 * A single watchpoint can create multiple requests. This method provides control over this

-	 * property for explicitly choosing which requests (access, modification, or both) to 

-	 * potentially add.

-	 */	

-	protected void selectiveWatchpointAdded(IMarker breakpoint, boolean accessCheck, boolean modificationCheck) {

-		String topLevelName= getTopLevelTypeName(breakpoint);

-		if (topLevelName == null) {

-			internalError(ERROR_BREAKPOINT_NO_TYPE);

-			return;

-		}

-		

-		List classes= jdiClassesByName(topLevelName);

-		if (classes == null || classes.isEmpty()) {

-			// defer

-			defer(breakpoint, topLevelName);

-			return;

-		}

-				

-		IField javaField= DebugJavaUtils.getField(breakpoint);

-		Field field= null;

-		ReferenceType reference= null;

-		for (int i=0; i<classes.size(); i++) {

-			reference= (ReferenceType) classes.get(i);

-			field= reference.fieldByName(javaField.getElementName());

-			if (field == null) {

-				return;

-			}

-			AccessWatchpointRequest accessRequest= null;

-			ModificationWatchpointRequest modificationRequest= null;			

-			// If we're not supposed to check access or modification, just retrieve the

-			// existing request

-			if (!accessCheck) {

-				accessRequest= getAccessWatchpointRequest(field);

-			}

-			if (!modificationCheck) {

-				modificationRequest= getModificationWatchpointRequest(field);

-			}

-			if (DebugJavaUtils.isAccess(breakpoint) && accessCheck) {

-				if (getVM().canWatchFieldAccess()) {

-					accessRequest= accessWatchpointAdded(breakpoint, field);

-				} else {

-					try {

-						notSupported(ERROR_ACCESS_WATCHPOINT_NOT_SUPPORTED);

-					} catch (DebugException e) {

-						internalError(e);

-					}

-				}

-			}

-			if (DebugJavaUtils.isModification(breakpoint) && modificationCheck) {

-				if (getVM().canWatchFieldModification()) {

-					modificationRequest= modificationWatchpointAdded(breakpoint, field);

-				} else {

-					try {

-						notSupported(ERROR_MODIFICATION_WATCHPOINT_NOT_SUPPORTED);

-					} catch (DebugException e) {

-						internalError(e);

-					}

-				}

-			}

-			if (!(accessRequest == null && modificationRequest == null)) {

-				Object[] requests= {accessRequest, modificationRequest};

-				fInstalledBreakpoints.put(breakpoint, requests);

-				try {		

-					DebugJavaUtils.incrementInstallCount(breakpoint);

-				} catch (CoreException e) {

-					internalError(e);

-				}				

-			}

-		}

-	}

-	

-	/**

-	 * An access watchpoint has been added.

-	 * Create or update the request.

-	 */

-	protected AccessWatchpointRequest accessWatchpointAdded(IMarker breakpoint, Field field) {

-		AccessWatchpointRequest request= getAccessWatchpointRequest(field);

-		if (request == null) {

-			request= createAccessWatchpoint(breakpoint, field);

-		}

-		// Important: Enable only after request has been configured

-		request.setEnabled(getBreakpointManager().isEnabled(breakpoint));

-		return request;

-	}

-	

-	/**

-	 * Create an access watchpoint for the given breakpoint and associated field

-	 */

-	protected AccessWatchpointRequest createAccessWatchpoint(IMarker breakpoint, Field field) {

-		AccessWatchpointRequest request= null;

-			try {

-				request= getEventRequestManager().createAccessWatchpointRequest(field);

-				configureRequest(request, breakpoint);

-			} catch (VMDisconnectedException e) {

-				return null;

-			} catch (RuntimeException e) {

-				internalError(e);

-				return null;

-			}

-		return request;

-	}	

-	

-	/**

-	 * A modification watchpoint has been added.

-	 * Create or update the request.

-	 */

-	protected ModificationWatchpointRequest modificationWatchpointAdded(IMarker breakpoint, Field field) {

-		ModificationWatchpointRequest request= getModificationWatchpointRequest(field);

-		if (request == null) {

-			request= createModificationWatchpoint(breakpoint, field);

-		}

-		// Important: only enable a request after it has been configured

-		request.setEnabled(getBreakpointManager().isEnabled(breakpoint));

-		return request;

-	}

-	

-	/**

-	 * Create a modification watchpoint for the given breakpoint and associated field

-	 */

-	protected ModificationWatchpointRequest createModificationWatchpoint(IMarker breakpoint, Field field) {

-		ModificationWatchpointRequest request= null;

-		try {

-			request= getEventRequestManager().createModificationWatchpointRequest(field);

-			configureRequest(request, breakpoint);

-		} catch (VMDisconnectedException e) {

-			return null;

-		} catch (RuntimeException e) {

-			internalError(e);

-			return null;

-		}

-		return request;			

-	}

-	

-	/**

-	 * Configure a request with common properties:

-	 * <ul>

-	 * <li><code>IDebugConstants.BREAKPOINT_MARKER</code></li>

-	 * <li><code>IJavaDebugConstants.HIT_COUNT</code></li>

-	 * <li><code>IJavaDebugConstants.EXPIRED</code></li>

-	 * </ul>

-	 * and sets the suspend policy of the request to suspend the event thread.

-	 */

-	protected void configureRequest(EventRequest request, IMarker breakpoint) {

-		request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);

-		request.putProperty(IDebugConstants.BREAKPOINT_MARKER, breakpoint);								

-		int hitCount= DebugJavaUtils.getHitCount(breakpoint);

-		if (hitCount > 0) {

-			request.addCountFilter(hitCount);

-			request.putProperty(IJavaDebugConstants.HIT_COUNT, new Integer(hitCount));

-			request.putProperty(IJavaDebugConstants.EXPIRED, Boolean.FALSE);

-		}

-	}

-	

-	/**

-	 * Enable a request and increment the install count of the associated breakpoint.

-	 */

-	protected void completeConfiguration(EventRequest request, IMarker breakpoint) {

-		// Important: Enable only after request has been configured

-		request.setEnabled(getBreakpointManager().isEnabled(breakpoint));		

-		try {		

-			DebugJavaUtils.incrementInstallCount(breakpoint);

-		} catch (CoreException e) {

-			internalError(e);

-		}

-	}		

-	

-	/**

-	 * A method entry breakpoint has been added.

-     * Create or update the request.

-	 */

-	protected void methodEntryBreakpointAdded(IMarker breakpoint) {

-		IType type = DebugJavaUtils.getType(breakpoint);

-		if (type == null) {

-			internalError(ERROR_BREAKPOINT_NO_TYPE);

-			return;

-		}

-		String className = type.getFullyQualifiedName();

-		

-		MethodEntryRequest request = getMethodEntryRequest(className);

-		

-		if (request == null) {

-			try {

-				request= getEventRequestManager().createMethodEntryRequest();

-				request.addClassFilter(className);

-				request.putProperty(CLASS_NAME, className);

-				request.putProperty(BREAKPOINT_INFO, new ArrayList(1));

-				request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);

-				request.putProperty(IDebugConstants.BREAKPOINT_MARKER, new ArrayList(3));

-				request.putProperty(IJavaDebugConstants.HIT_COUNT, new ArrayList(3));

-			} catch (VMDisconnectedException e) {

-				return;

-			} catch (RuntimeException e) {

-				internalError(e);

-				return;

-			}

-		}

-		List breakpointInfo= (List)request.getProperty(BREAKPOINT_INFO);

-		breakpointInfo.add(null);

-		

-		List breakpoints= (List)request.getProperty(IDebugConstants.BREAKPOINT_MARKER);

-		breakpoints.add(breakpoint);

-		

-		

-		List hitCounts = (List)request.getProperty(IJavaDebugConstants.HIT_COUNT);

-		int hitCount = DebugJavaUtils.getHitCount(breakpoint);

-		if (hitCount > 0) {

-			hitCounts.add(new Integer(hitCount));

-		} else {

-			hitCounts.add(null);

-		}

-		completeConfiguration(request, breakpoint);

-		fInstalledBreakpoints.put(breakpoint, request);

+	public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {

+		breakpoint.changeForTarget(this);

 	}

 	

 	/**

@@ -1356,152 +778,18 @@
 		Iterator requests= getEventRequestManager().methodEntryRequests().iterator();

 		while (requests.hasNext()) {

 			MethodEntryRequest existingRequest= (MethodEntryRequest)requests.next();

-			if (className.equals(existingRequest.getProperty(CLASS_NAME))) {

+			if (className.equals(existingRequest.getProperty(MethodEntryBreakpoint.CLASS_NAME))) {

 				return existingRequest;

 			}

 		}

 		return null;

 	}

-	

-	/**

-	 * A watchpoint has been changed.

-	 * Update the request.

-	 */

-	protected void watchpointChanged(IMarker breakpoint) {

-		Object[] requests= (Object[])fInstalledBreakpoints.get(breakpoint);		

-		for (int i=0; i < requests.length; i++) {

-			WatchpointRequest request= (WatchpointRequest)requests[i];

-			if (request == null) {

-				if ((i == 0) && DebugJavaUtils.isAccess(breakpoint)) {

-					selectiveWatchpointAdded(breakpoint, true, false);

-				}

-				if ((i == 1) && DebugJavaUtils.isModification(breakpoint)) {

-					selectiveWatchpointAdded(breakpoint, false, true);

-				}

-				continue;

-			}

-			if ((!DebugJavaUtils.isAccess(breakpoint) && (request instanceof AccessWatchpointRequest)) ||

-			(!DebugJavaUtils.isModification(breakpoint) && (request instanceof ModificationWatchpointRequest))) {

-				getEventRequestManager().deleteEventRequest(request); // disable & remove

-				continue;

-			}

-			request= (WatchpointRequest)updateHitCount(request, breakpoint);

-

-			if (request != null) {

-				updateEnabledState(request, breakpoint);					

-				requests[i]= request;

-			}				

-		}

-	}

-

-	/**

-	 * A method entry breakpoint has been changed.

-	 * Update the request.

-	 */

-	protected void methodEntryBreakpointChanged(IMarker breakpoint, IMarkerDelta delta) {

-		MethodEntryRequest request = (MethodEntryRequest)fInstalledBreakpoints.get(breakpoint);

-		if (request == null) {

-			return;

-		}

-		// check the enabled state

-		updateMethodEntryEnabledState(request);

-		

-		List breakpoints= (List)request.getProperty(IDebugConstants.BREAKPOINT_MARKER);

-		int index= breakpoints.indexOf(breakpoint);

-		// update the breakpoints hit count

-		int newCount = DebugJavaUtils.getHitCount(breakpoint);

-		List hitCounts= (List)request.getProperty(IJavaDebugConstants.HIT_COUNT);

-		if (newCount > 0) {

-			hitCounts.set(index, new Integer(newCount));

-		} else {

-			//back to a regular breakpoint

-			hitCounts.set(index, null);			

-		}

-	}

-	

-	/**

-	 * A watchpoint has been removed.

-	 * Remove the request.

-	 */

-	protected void watchpointRemoved(IMarker breakpoint) {

-		Object[] requests= (Object[]) fInstalledBreakpoints.remove(breakpoint);

-		if (requests == null) {

-			//deferred breakpoint

-			if (!breakpoint.exists()) {

-				//resource no longer exists

-				return;

-			}

-			String name= getTopLevelTypeName(breakpoint);

-			if (name == null) {

-				internalError(ERROR_BREAKPOINT_NO_TYPE);

-				return;

-			}

-			List markers= (List) fDeferredBreakpointsByClass.get(name);

-			if (markers == null) {

-				return;

-			}

-

-			markers.remove(breakpoint);

-			if (markers.isEmpty()) {

-				fDeferredBreakpointsByClass.remove(name);

-			}

-		} else {

-			//installed breakpoint

-			try {

-				for (int i=0; i<requests.length; i++) {

-					WatchpointRequest request= (WatchpointRequest)requests[i];

-					if (request == null) {

-						continue;

-					}

-					getEventRequestManager().deleteEventRequest(request); // disable & remove					

-				}

-				try {

-					DebugJavaUtils.decrementInstallCount(breakpoint);

-				} catch (CoreException e) {

-					internalError(e);

-				}			

-			} catch (VMDisconnectedException e) {

-				return;

-			} catch (RuntimeException e) {

-				internalError(e);

-			}

-		}

-	}

-

-	/**

-	 * A method entry breakpoint has been removed.

-	 * Update the request.

-	 */

-	protected void methodEntryBreakpointRemoved(IMarker breakpoint) {

-		MethodEntryRequest request = (MethodEntryRequest)fInstalledBreakpoints.remove(breakpoint);

-		if (request != null) {

-			try {

-				DebugJavaUtils.decrementInstallCount(breakpoint);

-			} catch (CoreException e) {

-				internalError(e);

-			}

-			List breakpoints= (List)request.getProperty(IDebugConstants.BREAKPOINT_MARKER);

-			int index = breakpoints.indexOf(breakpoint);

-			breakpoints.remove(index);

-			if (breakpoints.isEmpty()) {

-				try {

-					getEventRequestManager().deleteEventRequest(request); // disable & remove

-				} catch (VMDisconnectedException e) {

-				} catch (RuntimeException e) {

-					internalError(e);

-				}

-			} else {

-				List hitCounts= (List)request.getProperty(IJavaDebugConstants.HIT_COUNT);

-				hitCounts.remove(index);

-			}

-		}

-	}

 

 	/**

 	 * @see IBreakpointSupport

 	 */

-	public boolean supportsBreakpoint(IMarker breakpoint) {

-		return !isTerminated() && !isDisconnected() && JDIDebugModel.getPluginIdentifier().equals(getBreakpointManager().getModelIdentifier(breakpoint));

+	public boolean supportsBreakpoint(IBreakpoint breakpoint) {

+		return !isTerminated() && !isDisconnected() && JDIDebugModel.getPluginIdentifier().equals(breakpoint.getModelIdentifier());

 	}

 

 	/**

@@ -1575,15 +863,15 @@
 			//inner class load...resolve the top level type name

 			topLevelName= className.substring(0, index);

 		}

-		ArrayList markers= (ArrayList) fDeferredBreakpointsByClass.remove(topLevelName);

-		if (markers != null) {

+		ArrayList breakpoints= (ArrayList) fDeferredBreakpointsByClass.remove(topLevelName);

+		if (breakpoints != null) {

 			//no longer need to listen for this class load

 			ClassPrepareRequest request= (ClassPrepareRequest) fClassPrepareRequestsByClass.remove(topLevelName);

 			getEventRequestManager().deleteEventRequest(request);

-			Iterator itr= ((ArrayList) markers.clone()).iterator();

+			Iterator itr= ((ArrayList) breakpoints.clone()).iterator();

 			while (itr.hasNext()) {

-				IMarker marker= (IMarker) itr.next();

-				breakpointAdded(marker);

+				JavaBreakpoint breakpoint= (JavaBreakpoint) itr.next();

+				breakpoint.addToTarget(this);

 			}			

 		}

 	}

@@ -1592,11 +880,11 @@
 	 * Sets all the breakpoints to be uninstalled.

 	 */

 	protected void uninstallAllBreakpoints() {

-		Iterator markers= ((Map)((HashMap)fInstalledBreakpoints).clone()).keySet().iterator();

-		while (markers.hasNext()) {

-			IMarker marker= (IMarker) markers.next();

+		Iterator breakpoints= ((Map)((HashMap)fInstalledBreakpoints).clone()).keySet().iterator();

+		while (breakpoints.hasNext()) {

+			JavaBreakpoint breakpoint= (JavaBreakpoint) breakpoints.next();

 			try {

-				DebugJavaUtils.decrementInstallCount(marker);				

+				breakpoint.decrementInstallCount();				

 			} catch (CoreException e) {

 				internalError(e);

 			}

@@ -1607,53 +895,8 @@
 	/**

 	 * @see IBreakpointSupport

 	 */

-	public void breakpointRemoved(IMarker breakpoint, IMarkerDelta delta) {

-		if (DebugJavaUtils.isExceptionBreakpoint(breakpoint)) {

-			exceptionBreakpointRemoved(breakpoint);

-		} else if (DebugJavaUtils.isMethodEntryBreakpoint(breakpoint)) {

-			methodEntryBreakpointRemoved(breakpoint);

-		} else if (DebugJavaUtils.isWatchpoint(breakpoint)) {

-			watchpointRemoved(breakpoint);

-		} else {

-			lineBreakpointRemoved(breakpoint);

-		}

-	}

-	

-	protected void lineBreakpointRemoved(IMarker breakpoint) {		

-		BreakpointRequest request= (BreakpointRequest) fInstalledBreakpoints.remove(breakpoint);

-		if (request == null) {

-			//deferred breakpoint

-			if (!breakpoint.exists()) {

-				//resource no longer exists

-				return;

-			}

-			String name= getTopLevelTypeName(breakpoint);

-			if (name == null) {

-				internalError(ERROR_BREAKPOINT_NO_TYPE);

-				return;

-			}

-			List markers= (List) fDeferredBreakpointsByClass.get(name);

-			if (markers == null) {

-				return;

-			}

-

-			markers.remove(breakpoint);

-			if (markers.isEmpty()) {

-				fDeferredBreakpointsByClass.remove(name);

-			}

-		} else {

-			//installed breakpoint

-			try {

-				// cannot delete an expired request

-				if (!isExpired(request)) {

-					getEventRequestManager().deleteEventRequest(request); // disable & remove

-				}

-			} catch (VMDisconnectedException e) {

-				return;

-			} catch (RuntimeException e) {

-				internalError(e);

-			}

-		}

+	public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {

+		breakpoint.removeFromTarget(this);

 	}

 

 	/**

@@ -1666,16 +909,9 @@
 			while (itr.hasNext()) {

 				// do not notify the breakpoint manager of uninstall, as we

 				// are in a resource change callback and cannot modify the resource tree

-				IMarker marker= (IMarker) itr.next();

-				boolean watchpointMarker= false;

-				try {

-					watchpointMarker= marker.isSubtypeOf(IJavaDebugConstants.JAVA_WATCHPOINT);

-				} catch (CoreException ce) {

-					logError(ce);

-					continue;

-				}

-				if (watchpointMarker) {

-					Object[] requests= (Object[])fInstalledBreakpoints.remove(marker);

+				JavaBreakpoint breakpoint= (JavaBreakpoint) itr.next();

+				if (breakpoint instanceof Watchpoint) {

+					Object[] requests= (Object[])fInstalledBreakpoints.remove(breakpoint);

 					for (int i=0; i<requests.length; i++) {

 						EventRequest req = (EventRequest)requests[i];

 						if (req != null) {

@@ -1683,10 +919,10 @@
 						}

 					}

 				} else {

-					EventRequest req = (EventRequest)fInstalledBreakpoints.remove(marker);

+					EventRequest req = (EventRequest)fInstalledBreakpoints.remove(breakpoint);

 					getEventRequestManager().deleteEventRequest(req);

 				}

-				breakpointAdded(marker);

+				breakpoint.addToTarget(this);

 			}

 		}

 	}

@@ -1755,29 +991,6 @@
 		}

 		return null;

 	}

-		

-	/**

-	 * Called by a JDI thread when a breakpoint or 

-	 * watchpoint is encountered.

-	 */

-	public void expireHitCount(LocatableEvent event) {

-		EventRequest request= (EventRequest)event.request();

-		Integer requestCount= (Integer) request.getProperty(IJavaDebugConstants.HIT_COUNT);

-		if (requestCount != null) {

-			IMarker breakpoint= (IMarker)request.getProperty(IDebugConstants.BREAKPOINT_MARKER);

-			if (breakpoint == null) {

-				return;

-			}

-			try {

-				request.putProperty(IJavaDebugConstants.EXPIRED, Boolean.TRUE);

-				getBreakpointManager().setEnabled(breakpoint, false);

-				// make a note that we auto-disabled this breakpoint.

-				DebugJavaUtils.setExpired(breakpoint, true);

-			} catch (CoreException ce) {

-				internalError(ce);

-			}

-		}

-	}

 	

 	/**

 	 * @see IDebugElement

@@ -1792,7 +1005,7 @@
 	 * 

 	 * @see IAdaptable

 	 */

-	protected Object getAdpater(Class adapter) {

+	public Object getAdapter(Class adapter) {

 		if (adapter == IJavaDebugTarget.class) {

 			return this;

 		}

@@ -1903,18 +1116,7 @@
 		}

 		return context;

 	}

-	

-	/**

-	 * Returns whether the given request is expired

-	 */

-	protected boolean isExpired(EventRequest request) {

-		Boolean requestExpired= (Boolean) request.getProperty(IJavaDebugConstants.EXPIRED);

-		if (requestExpired == null) {

-				return false;

-		}

-		return requestExpired.booleanValue();

-	}

-	

+

 	/**

 	 * The JDIDebugPlugin is shutting down.

 	 * Shutdown the event dispatcher.

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIThread.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIThread.java
index 8cb02c1..cf6f26f 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIThread.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIThread.java
@@ -109,7 +109,7 @@
 	 * The breakpoint that caused the last suspend, or

 	 * <code>null</code> if none.

 	 */

-	protected IMarker fCurrentBreakpoint;

+	protected JavaBreakpoint fCurrentBreakpoint;

 

 	/**

 	 * The cached named of the underlying thread.

@@ -137,7 +137,6 @@
 	 * invocations cannot be performed.

 	 */

 	protected boolean fInEvaluation = false;

-	protected boolean fEvaluationAborted = false;

 

 	/**

 	 * Creates a new thread on the underlying thread reference.

@@ -191,7 +190,7 @@
 	/**

 	 * @see IJavaThread

 	 */

-	public IMarker getBreakpoint() {

+	public JavaBreakpoint getBreakpoint() {

 		if (fCurrentBreakpoint != null && !fCurrentBreakpoint.exists()) {

 			fCurrentBreakpoint= null;

 		}

@@ -444,24 +443,10 @@
 		}

 

 		invokeComplete(timeout);

-		if (fEvaluationAborted) {

-			fEvaluationAborted = false;

-			resume();

-		}

 		return result;

 	}

 	

 	/**

-	 * Called by JDIValue when an evaluation of

-	 * #toString times out. Causes this thread to

-	 * be automatically resumed when it returns from

-	 * its evaluation - see <code>invokeMethod</code>.

-	 */

-	protected void abortEvaluation() {

-		fEvaluationAborted = true;

-	}

-	

-	/**

 	 * Invokes a method in this thread, creating a new instance of the given

 	 * class using the specified constructor, and returns the result.

 	 */

@@ -595,24 +580,11 @@
 	 */

 	protected void handleLocatableEvent(LocatableEvent event) {

 		abortDropAndStep();

-		fCurrentBreakpoint= (IMarker) event.request().getProperty(IDebugConstants.BREAKPOINT_MARKER);

+		fCurrentBreakpoint= (JavaBreakpoint) event.request().getProperty(IDebugConstants.BREAKPOINT);

 		setRunning(false, DebugEvent.BREAKPOINT);

-		((JDIDebugTarget) getDebugTarget()).expireHitCount(event);

 	}

 	

-	/**

-	 * Suspend the thread based on an exception event

-	 */

-	protected void handleException(ExceptionEvent event) {

-		abortDropAndStep();

-		fCurrentBreakpoint= (IMarker) event.request().getProperty(IDebugConstants.BREAKPOINT_MARKER);

-		setRunning(false, DebugEvent.BREAKPOINT);

-	}

-

-	/**

-	 * Suspend the thread based on the method entry event

-	 */

-	protected void handleSuspendMethodEntry(IMarker breakpoint) {

+	protected void handleSuspendForBreakpoint(JavaBreakpoint breakpoint) {

 		abortDropAndStep();

 		fCurrentBreakpoint= breakpoint;

 		setRunning(false, DebugEvent.BREAKPOINT);

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIValue.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIValue.java
index aa1e95c..c2c76ef 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIValue.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JDIValue.java
Binary files differ
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JavaBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JavaBreakpoint.java
new file mode 100644
index 0000000..7c0adf8
--- /dev/null
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JavaBreakpoint.java
@@ -0,0 +1,383 @@
+package org.eclipse.jdt.internal.debug.core;

+

+import java.text.MessageFormat;

+import java.util.ArrayList;

+import java.util.List;

+

+import org.eclipse.core.resources.*;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.debug.core.*;

+import org.eclipse.debug.core.model.IDebugTarget;

+import org.eclipse.debug.internal.core.Breakpoint;

+import org.eclipse.jdt.core.IType;

+import org.eclipse.jdt.core.JavaCore;

+import org.eclipse.jdt.debug.core.IJavaDebugConstants;

+

+import com.sun.jdi.VMDisconnectedException;

+import com.sun.jdi.VirtualMachine;

+import com.sun.jdi.event.Event;

+import com.sun.jdi.request.EventRequest;

+import com.sun.jdi.request.MethodEntryRequest;

+

+public abstract class JavaBreakpoint extends Breakpoint {

+

+	// Thread and marker label resource String keys

+	protected static final String THREAD_PREFIX= "jdi_thread.";

+	protected static final String MARKER_PREFIX= "jdi_marker.";

+	protected static final String LABEL= "label.";	

+	protected static final String THREAD_LABEL= THREAD_PREFIX + LABEL;

+	protected static final String MARKER_LABEL= MARKER_PREFIX + LABEL;

+	/**

+	 * JavaBreakpoint attributes

+	 */	

+	protected static final String[] fgExpiredEnabledAttributes= new String[]{IJavaDebugConstants.EXPIRED, IDebugConstants.ENABLED};			

+

+	protected JDIDebugTarget fTarget= null;

+	

+	public JavaBreakpoint() {

+	}	

+	

+	public JavaBreakpoint(IMarker marker) {

+		super(marker);

+	}

+

+	/**

+	 * @see Breakpoint#addToTarget(IDebugTarget)

+	 */

+	public void addToTarget(IDebugTarget target) {

+		if (target instanceof JDIDebugTarget) {

+			addToTarget((JDIDebugTarget) target);

+		}

+	}

+	

+	/**

+	 * This breakpoint is being added to the target

+	 * Create or update the request.

+	 */

+	public abstract void addToTarget(JDIDebugTarget target);	

+

+	/**

+	 * @see Breakpoint#changeForTarget

+	 */

+	public void changeForTarget(IDebugTarget target) {

+		if (target instanceof JDIDebugTarget) {

+			changeForTarget((JDIDebugTarget) target);

+		}

+	}

+	

+	/**

+	 * This breakpoint has been changed.

+	 * Update the request from the given target.

+	 */

+	public abstract void changeForTarget(JDIDebugTarget target);

+	

+	/**

+	 * @see Breakpoint#removeFromTarget(IDebugTarget)

+	 */

+	public void removeFromTarget(IDebugTarget target) {

+		if (target instanceof JDIDebugTarget) {

+			removeFromTarget((JDIDebugTarget) target);

+		}

+	}

+	

+	/**

+	 * This breakpoint has been removed.

+	 * Remove the request from the given target.

+	 */

+	public abstract void removeFromTarget(JDIDebugTarget target);

+

+	/**

+	 * Update the enabled state of the given request, which is associated

+	 * with this breakpoint. Set the enabled state of the request

+	 * to the enabled state of this breakpoint.

+	 */

+	protected void updateEnabledState(EventRequest request)  {

+		updateEnabledState0(request, this.isEnabled());

+	}

+

+	/**

+	 * Set the enabled state of the given request as specified by the enabled

+	 * parameter

+	 */

+	protected void updateEnabledState0(EventRequest request, boolean enabled) {

+		if (request.isEnabled() != enabled) {

+			// change the enabled state

+			try {

+				// if the request has expired, and is not a method entry request, do not disable.

+				// BreakpointRequests that have expired cannot be deleted. However method entry 

+				// requests that are expired can be deleted (since we simulate the hit count)

+				if (request instanceof MethodEntryRequest || !isExpired(request)) {

+					request.setEnabled(enabled);

+				}

+			} catch (VMDisconnectedException e) {

+			} catch (RuntimeException e) {

+				logError(e);

+			}

+		}

+	}

+	

+	/**

+	 * Returns whether this kind of breakpoint is supported by the given

+	 * virtual machine.

+	 */

+	public abstract boolean isSupportedBy(VirtualMachine vm);

+	

+	/**

+	 * Return whether this breakpoint is enabled

+	 */

+	public boolean isEnabled() {

+		try {

+			return super.isEnabled();

+		} catch (CoreException ce) {

+			logError(ce);

+			return false;

+		}

+	}

+	

+	/**

+	 * Returns whether this breakpoint has expired.

+	 */

+	public boolean isExpired() {

+		return getBooleanAttribute(IJavaDebugConstants.EXPIRED);

+	}	

+	

+	/**

+	 * Returns whether the given request is expired

+	 */

+	protected boolean isExpired(EventRequest request) {

+		Boolean requestExpired= (Boolean) request.getProperty(IJavaDebugConstants.EXPIRED);

+		if (requestExpired == null) {

+				return false;

+		}

+		return requestExpired.booleanValue();

+	}	

+

+	/**

+	 * An event request has been fired for this breakpoint. Handle it.

+	 */

+	public abstract void handleEvent(Event event, JDIDebugTarget target);

+	

+	/**

+	 * Enable this breakpoint

+	 */

+	public void enable() {

+		try {

+			super.enable();

+		} catch (CoreException ce) {

+			logError(ce);

+		}

+	}

+	

+	/**

+	 * Disable this breakpoint

+	 */

+	public void disable() {

+		try {

+			super.disable();

+		} catch (CoreException ce) {

+			logError(ce);

+		}

+	}

+	

+	/**

+	 * Returns whether this breakpoint is installed in at least

+	 * one debug target.

+	 */

+	public boolean isInstalled() {

+		return getAttribute(IJavaDebugConstants.INSTALL_COUNT, 0) > 0;

+	}	

+	

+	/**

+	 * Increments the install count on this breakpoint

+	 */

+	public void incrementInstallCount() throws CoreException {

+		int count = getInstallCount();

+		setAttribute(IJavaDebugConstants.INSTALL_COUNT, count + 1);

+	}	

+	

+	/**

+	 * Returns the <code>INSTALL_COUNT</code> attribute of this breakpoint

+	 * or 0 if the attribute is not set.

+	 */

+	public int getInstallCount() {

+		return getAttribute(IJavaDebugConstants.INSTALL_COUNT, 0);

+	}	

+

+	/**

+	 * Decrements the install count on this breakpoint. If the new

+	 * install count is 0, the <code>EXPIRED</code> attribute is reset to

+	 * <code>false</code> (since any hit count breakpoints that auto-expired

+	 * should be re-enabled when the debug session is over).

+	 */

+	public void decrementInstallCount() throws CoreException {

+		int count= getInstallCount();

+		if (count > 0) {

+			setAttribute(IJavaDebugConstants.INSTALL_COUNT, count - 1);	

+		}

+		if (count == 1) {

+			if (isExpired()) {

+				// if breakpoint was auto-disabled, re-enable it

+				setAttributes(fgExpiredEnabledAttributes,

+						new Object[]{Boolean.FALSE, Boolean.TRUE});

+			}

+		}

+	}

+

+	/**

+	 * Sets the <code>TYPE_HANDLE</code> attribute of the given breakpoint, associated

+	 * with the given IType.

+	 */

+	public void setType(IType type) throws CoreException {

+		String handle = type.getHandleIdentifier();

+		setTypeHandleIdentifier(handle);

+	}

+	

+	/**

+	 * Sets the <code>TYPE_HANDLE</code> attribute of the given breakpoint.

+	 */

+	public void setTypeHandleIdentifier(String identifier) throws CoreException {

+		setAttribute(IJavaDebugConstants.TYPE_HANDLE, identifier);

+	}

+	

+	/**

+	 * Returns the type the given breakpoint is installed in

+	 * or <code>null</code> a type cannot be resolved.

+	 */

+	public IType getBreakpointType() {

+		try {

+			String handle = getTypeHandleIdentifier();

+			if (handle != null) {

+				return (IType)JavaCore.create(handle);

+			}

+		} catch (CoreException e) {

+			logError(e);

+		}

+		return null;

+	}	

+	

+	/**

+	 * Returns the <code>TYPE_HANDLE</code> attribute of the given breakpoint.

+	 */

+	public String getTypeHandleIdentifier() throws CoreException {

+		return (String)getAttribute(IJavaDebugConstants.TYPE_HANDLE);

+	}	

+	

+	/**

+	 * Returns the top-level type name associated with the type 

+	 * the given breakpoint is associated with, or <code>null</code>.

+	 */

+	public String getTopLevelTypeName() {

+		IType type = getBreakpointType();

+		if (type != null) {

+			while (type.getDeclaringType() != null) {

+				type = type.getDeclaringType();

+			}

+			return type.getFullyQualifiedName();

+		}

+		return null;

+	}

+	

+	/**

+	 * Returns the text that should be displayed on a thread when the

+	 * breakpoint is hit.

+	 */

+	public String getThreadText(String threadName, boolean qualified, boolean systemThread) {

+		String typeName= getBreakpointTypeName(qualified);

+		return getFormattedThreadText(threadName, typeName, systemThread);			

+	}

+	

+	/**

+	 * Returns the formatted text that should be displayed on a thread

+	 * when the breakpoint is hit.

+	 */

+	public abstract String getFormattedThreadText(String threadName, String typeName, boolean systemThread);

+	

+	public String getBreakpointTypeName(boolean qualified) {

+		String typeName= "";

+		typeName= getBreakpointType().getFullyQualifiedName();

+		if (!qualified) {

+			int index= typeName.lastIndexOf('.');

+			if (index != -1) {

+				typeName= typeName.substring(index + 1);

+			}

+		}

+		return typeName;

+	}		

+	

+	/**

+	 * Returns the identifier for this JDI debug model plug-in

+	 *

+	 * @return plugin identifier

+	 */

+	public static String getPluginIdentifier() {

+		return JDIDebugPlugin.getDefault().getDescriptor().getUniqueIdentifier();

+	}	

+

+	/**

+	 * Plug in the single argument to the resource String for the key to get a formatted resource String

+	 */

+	public static String getFormattedString(String key, String arg) {

+		return getFormattedString(key, new String[] {arg});

+	}

+

+	/**

+	 * Plug in the arguments to the resource String for the key to get a formatted resource String

+	 */

+	public static String getFormattedString(String key, String[] args) {

+		String string= DebugJavaUtils.getResourceString(key);

+		return MessageFormat.format(string, args);

+	}

+

+	/**

+	 * Returns the VM this breakpoint is contained in

+	 * or <code>null</code> if it is not installed.

+	 */

+	public VirtualMachine getVM() {

+		if (fTarget == null) {

+			return null;

+		}

+		return fTarget.getVM();

+	}

+	

+	/**

+	 * Convenience method to log internal errors

+	 */

+	protected void logError(Exception e) {

+		DebugJavaUtils.logError(e);

+	}	

+	

+	protected void run(IWorkspaceRunnable wr) throws DebugException {

+		try {

+			ResourcesPlugin.getWorkspace().run(wr, null);

+		} catch (CoreException e) {

+			throw new DebugException(e.getStatus());

+		}			

+	}

+	

+	/**

+	 * Resets the install count attribute on the breakpoint marker

+	 * to "0".  Resets the expired attribute on the breakpoint marker to <code>false</code>.

+	 * Resets the enabled attribute on the breakpoint marker to <code>true</code>.

+	 */

+	protected void configureBreakpointAtStartup() throws CoreException {

+		List attributes= new ArrayList(3);

+		List values= new ArrayList(3);

+		if (isInstalled()) {

+			attributes.add(IJavaDebugConstants.INSTALL_COUNT);

+			values.add(new Integer(0));

+		}

+		if (isExpired()) {

+			// if breakpoint was auto-disabled, re-enable it

+			attributes.add(IJavaDebugConstants.EXPIRED);

+			values.add(Boolean.FALSE);

+			attributes.add(IDebugConstants.ENABLED);

+			values.add(Boolean.TRUE);

+		}

+		if (!attributes.isEmpty()) {

+			String[] strAttributes= new String[attributes.size()];

+			setAttributes((String[])attributes.toArray(strAttributes), values.toArray());

+		}

+	}	

+

+}

+

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JavaBreakpointFactory.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JavaBreakpointFactory.java
new file mode 100644
index 0000000..90f079c
--- /dev/null
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/JavaBreakpointFactory.java
@@ -0,0 +1,37 @@
+package org.eclipse.jdt.internal.debug.core;

+

+import org.eclipse.core.resources.IMarker;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.debug.core.DebugException;

+import org.eclipse.debug.core.IBreakpoint;

+import org.eclipse.debug.core.model.IBreakpointFactoryDelegate;

+import org.eclipse.jdt.debug.core.IJavaDebugConstants;

+

+public class JavaBreakpointFactory implements IBreakpointFactoryDelegate {

+

+	public JavaBreakpointFactory() {

+	}

+	

+	public IBreakpoint createBreakpointFor(IMarker marker) throws DebugException {

+		String markerType= null;

+		try {

+			markerType= marker.getType();

+		} catch (CoreException ce) {

+			throw new DebugException(ce.getStatus());

+		}

+		if (markerType.equals(IJavaDebugConstants.JAVA_LINE_BREAKPOINT)) {

+			return new LineBreakpoint(marker);

+		} else if (markerType.equals(IJavaDebugConstants.JAVA_WATCHPOINT)) {

+			return new Watchpoint(marker);

+		} else if (markerType.equals(IJavaDebugConstants.JAVA_METHOD_ENTRY_BREAKPOINT)) {

+			return new MethodEntryBreakpoint(marker);

+		} else if (markerType.equals(IJavaDebugConstants.JAVA_RUN_TO_LINE_BREAKPOINT)) {

+			return new RunToLineBreakpoint(marker);

+		} else if (markerType.equals(IJavaDebugConstants.JAVA_EXCEPTION_BREAKPOINT)) {

+			return new ExceptionBreakpoint(marker);

+		}

+		return null;

+	}

+

+}

+

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/LineBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/LineBreakpoint.java
new file mode 100644
index 0000000..082bf2a
--- /dev/null
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/LineBreakpoint.java
@@ -0,0 +1,573 @@
+package org.eclipse.jdt.internal.debug.core;

+

+import java.util.*;

+

+import org.eclipse.core.resources.*;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.debug.core.DebugException;

+import org.eclipse.debug.core.IDebugConstants;

+import org.eclipse.jdt.core.*;

+import org.eclipse.jdt.debug.core.IJavaDebugConstants;

+

+import com.sun.jdi.*;

+import com.sun.jdi.event.Event;

+import com.sun.jdi.event.LocatableEvent;

+import com.sun.jdi.request.BreakpointRequest;

+import com.sun.jdi.request.EventRequest;

+

+public class LineBreakpoint extends JavaBreakpoint {

+	

+	// Thread label String keys

+	private static final String LINE_BREAKPOINT_SYS= THREAD_LABEL + "line_breakpoint_sys";

+	private static final String LINE_BREAKPOINT_USR= THREAD_LABEL + "line_breakpoint_usr";

+	// Marker label String keys

+	private static final String LINE= "line";

+	private static final String HITCOUNT= "hitCount";

+		

+	static String fMarkerType= IJavaDebugConstants.JAVA_LINE_BREAKPOINT;

+	/**

+	 * Sets of attributes used to configure a line breakpoint

+	 */

+	protected static final String[] fgTypeAndHitCountAttributes= new String[]{IJavaDebugConstants.TYPE_HANDLE, IJavaDebugConstants.HIT_COUNT, IJavaDebugConstants.EXPIRED};	

+	protected static final String[] fgLineBreakpointAttributes= new String[]{IDebugConstants.MODEL_IDENTIFIER, IDebugConstants.ENABLED, IMarker.LINE_NUMBER, IMarker.CHAR_START, IMarker.CHAR_END};		

+	

+	public LineBreakpoint(){

+	}

+	

+	public LineBreakpoint(IMarker marker) {

+		super(marker);

+	}

+	

+	public LineBreakpoint(IType type, int lineNumber, int charStart, int charEnd, int hitCount) throws DebugException {

+		this(type, lineNumber, charStart, charEnd, hitCount, fMarkerType);

+	}

+	

+	public LineBreakpoint(final IType type, final int lineNumber, final int charStart, final int charEnd, final int hitCount, final String markerType) throws DebugException {

+		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

+				fMarker= resource.createMarker(markerType);

+				setLineBreakpointAttributes(getPluginIdentifier(), true, lineNumber, charStart, charEnd);

+	

+				// configure the hit count and type handle

+				setTypeAndHitCount(type, hitCount);

+	

+				// configure the marker as a Java marker

+				Map attributes= getAttributes();

+				JavaCore.addJavaElementMarkerAttributes(attributes, type);

+				setAttributes(attributes);	

+			}

+		};

+		run(wr);

+	}		

+	

+	/**

+	 * @see JavaBreakpoint#installIn(JDIDebugTarget)

+	 */

+	public void addToTarget(JDIDebugTarget target) {

+		String topLevelName= getTopLevelTypeName();

+		if (topLevelName == null) {

+//			internalError(ERROR_BREAKPOINT_NO_TYPE);

+			return;

+		}

+		

+		// look for the top-level class - if it is loaded, inner classes may also be loaded

+		List classes= target.jdiClassesByName(topLevelName);

+		if (classes == null || classes.isEmpty()) {

+			// defer

+			target.defer(this, topLevelName);

+		} else {

+			// try to install

+			ReferenceType type= (ReferenceType) classes.get(0);

+			if (!installLineBreakpoint(target, type)) {

+				// install did not succeed - could be an inner type not yet loaded

+				target.defer(this, topLevelName);

+			}

+		}

+	}	

+	

+	/**

+	 * Installs a line breakpoint in the given type, returning whether successful.

+	 */

+	protected boolean installLineBreakpoint(JDIDebugTarget target, ReferenceType type) {

+		Location location= null;

+		int lineNumber= getLineNumber();			

+		location= determineLocation(lineNumber, type);

+		if (location == null) {

+			// could be an inner type not yet loaded, or line information not available

+			return false;

+		}

+		

+		if (createLineBreakpointRequest(location, target) != null) {

+			// update the install attibute on the breakpoint

+			if (!target.inHCR()) {

+				try {

+					incrementInstallCount();

+				} catch (CoreException e) {

+					logError(e);

+				}

+			}

+			return true;

+		} else {

+			return false;

+		}

+		

+	}	

+	

+	/**

+	 * Creates, installs, and returns a line breakpoint request at

+	 * the given location for the given breakpoint.

+	 */

+	protected BreakpointRequest createLineBreakpointRequest(Location location, JDIDebugTarget target) {

+		BreakpointRequest request = null;

+		try {

+			request= target.getEventRequestManager().createBreakpointRequest(location);

+			configureRequest(request);

+		} catch (VMDisconnectedException e) {

+			target.uninstallBreakpoint(this);

+			return null;

+		} catch (RuntimeException e) {

+			target.uninstallBreakpoint(this);

+			logError(e);

+			return null;

+		}

+		request.setEnabled(isEnabled());

+		target.installBreakpoint(this, request);	

+		return request;

+	}

+	

+	

+	/**

+	 * Returns a location for the line number in the given type, or any of its

+	 * nested types. Returns <code>null</code> if a location cannot be determined.

+	 */

+	protected Location determineLocation(int lineNumber, ReferenceType type) {

+		List locations= null;

+		try {

+			locations= type.locationsOfLine(lineNumber);

+		} catch (AbsentInformationException e) {

+			return null;

+		} catch (NativeMethodException e) {

+			return null;

+		} catch (InvalidLineNumberException e) {

+			//possible in a nested type, fall through and traverse nested types

+		} catch (VMDisconnectedException e) {

+			return null;

+		} catch (ClassNotPreparedException e) {

+			// could be a nested type that is not yet loaded

+			return null;

+		} catch (RuntimeException e) {

+			// not able to retrieve line info

+			logError(e);

+			return null;

+		}

+		

+		if (locations != null && locations.size() > 0) {

+			return (Location) locations.get(0);

+		} else {

+			Iterator nestedTypes= null;

+			try {

+				nestedTypes= type.nestedTypes().iterator();

+			} catch (RuntimeException e) {

+				// not able to retrieve line info

+				logError(e);

+				return null;

+			}

+			while (nestedTypes.hasNext()) {

+				ReferenceType nestedType= (ReferenceType) nestedTypes.next();

+				Location innerLocation= determineLocation(lineNumber, nestedType);

+				if (innerLocation != null) {

+					return innerLocation;

+				}

+			}

+		}

+

+		return null;

+	}	

+	

+	public void changeForTarget(JDIDebugTarget target) {

+		BreakpointRequest request= (BreakpointRequest) target.getRequest(this);

+		if (request != null) {

+			// already installed - could be a change in the enabled state or hit count

+			//may result in a new request being generated

+			request= updateHitCount(request, target);

+			if (request != null) {

+				updateEnabledState(request);

+				target.installBreakpoint(this, request);				

+			}

+		}	

+	}

+	

+	/**

+	 * Update the hit count of an <code>EventRequest</code>. Return a new request with

+	 * the appropriate settings.

+	 */

+	protected BreakpointRequest updateHitCount(BreakpointRequest request, JDIDebugTarget target) {		

+		

+		// if the hit count has changed, or the request has expired and is being re-enabled,

+		// create a new request

+		if (hasHitCountChanged(request) || (isExpired(request) && this.isEnabled())) {

+			try {

+				// delete old request

+				//on JDK you cannot delete (disable) an event request that has hit its count filter

+				if (!isExpired(request)) {

+					target.getEventRequestManager().deleteEventRequest(request); // disable & remove

+				}				

+					Location location = ((BreakpointRequest) request).location();

+					request = createLineBreakpointRequest(location, target);

+			} catch (VMDisconnectedException e) {

+			} catch (RuntimeException e) {

+				logError(e);

+			}

+		}

+		return request;

+	}

+	

+	/**

+	 * Returns whether the hitCount of this breakpoint is equal to the hitCount of

+	 * the associated request.

+	 */

+	protected boolean hasHitCountChanged(EventRequest request) {

+		int hitCount= getHitCount();

+		Integer requestCount= (Integer) request.getProperty(IJavaDebugConstants.HIT_COUNT);

+		int oldCount = -1;

+		if (requestCount != null)  {

+			oldCount = requestCount.intValue();

+		} 

+		return hitCount != oldCount;

+	}

+		

+	

+	/**

+	 * Configure a breakpoint request with common properties:

+	 * <ul>

+	 * <li><code>IDebugConstants.BREAKPOINT_MARKER</code></li>

+	 * <li><code>IJavaDebugConstants.HIT_COUNT</code></li>

+	 * <li><code>IJavaDebugConstants.EXPIRED</code></li>

+	 * </ul>

+	 * and sets the suspend policy of the request to suspend the event thread.

+	 */

+	protected void configureRequest(EventRequest request) {

+		request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);

+		request.putProperty(IDebugConstants.BREAKPOINT, this);								

+		int hitCount= getHitCount();

+		if (hitCount > 0) {

+			request.addCountFilter(hitCount);

+			request.putProperty(IJavaDebugConstants.HIT_COUNT, new Integer(hitCount));

+			request.putProperty(IJavaDebugConstants.EXPIRED, Boolean.FALSE);

+		}

+	}	

+	

+	/**

+	 * Enable a request and increment the install count of the associated breakpoint.

+	 */

+	protected void completeConfiguration(EventRequest request) {

+		// Important: Enable only after request has been configured		

+		try {	

+			request.setEnabled(isEnabled());				

+			incrementInstallCount();

+		} catch (CoreException e) {

+			logError(e);

+		}

+	}		

+	

+	/**

+	 * @see JavaBreakpoint#handleEvent(Event)

+	 */

+	public void handleEvent(Event event, JDIDebugTarget target) {

+		if (!(event instanceof LocatableEvent)) {

+			return;

+		}

+		ThreadReference threadRef= ((LocatableEvent)event).thread();

+		JDIThread thread= target.findThread(threadRef);		

+		if (thread == null) {

+			target.resume(threadRef);

+			return;

+		} else {

+			thread.handleSuspendForBreakpoint(this);

+			expireHitCount((LocatableEvent)event);	

+		}			

+	}

+	

+	/**

+	 * Called when a breakpoint event is encountered

+	 */

+	public void expireHitCount(LocatableEvent event) {

+		EventRequest request= (EventRequest)event.request();

+		Integer requestCount= (Integer) request.getProperty(IJavaDebugConstants.HIT_COUNT);

+		if (requestCount != null) {

+			try {

+				request.putProperty(IJavaDebugConstants.EXPIRED, Boolean.TRUE);

+				this.disable();

+				// make a note that we auto-disabled this breakpoint.

+				setExpired(true);

+			} catch (CoreException ce) {

+				logError(ce);

+			}

+		}

+	}	

+	

+	/**

+	 * @see JavaBreakpoint#removeFromTarget(JDIDebugTarget)

+	 */

+	public void removeFromTarget(JDIDebugTarget target) {		

+		BreakpointRequest request= (BreakpointRequest) target.getRequest(this);

+		if (request == null) {

+			//deferred breakpoint

+			if (!this.exists()) {

+				//resource no longer exists

+				return;

+			}

+			String name= getTopLevelTypeName();

+			if (name == null) {

+//				internalError(ERROR_BREAKPOINT_NO_TYPE);

+				return;

+			}

+			List breakpoints= (List) target.getDeferredBreakpointsByClass(name);

+			if (breakpoints == null) {

+				return;

+			}

+

+			breakpoints.remove(this);

+			if (breakpoints.isEmpty()) {

+				target.removeDeferredBreakpointByClass(name);

+			}

+		} else {

+			//installed breakpoint

+			try {

+				// cannot delete an expired request

+				if (!isExpired(request)) {

+					target.getEventRequestManager().deleteEventRequest(request); // disable & remove

+				}

+			} catch (VMDisconnectedException e) {

+				return;

+			} catch (RuntimeException e) {

+				logError(e);

+			}

+		}

+	}	

+	

+	/**

+	 * Returns the <code>HIT_COUNT</code> attribute of the given breakpoint

+	 * or -1 if the attribute is not set.

+	 */

+	public int getHitCount() {

+		return getAttribute(IJavaDebugConstants.HIT_COUNT, -1);

+	}

+	

+	/**

+	 * Sets the <code>HIT_COUNT</code> attribute of the given breakpoint,

+	 * and resets the <code>EXPIRED</code> attribute to false (since, if

+	 * the hit count is changed, the breakpoint should no longer be expired).

+	 */

+	public void setHitCount(int count) throws CoreException {

+		setAttributes(new String[]{IJavaDebugConstants.HIT_COUNT, IJavaDebugConstants.EXPIRED},

+						new Object[]{new Integer(count), Boolean.FALSE});

+	}		

+	

+	/**

+	 * @see JavaBreakpoint#isSupportedBy(VirtualMachine)

+	 */

+	public boolean isSupportedBy(VirtualMachine vm) {

+		return true;

+	}

+	

+	/**

+	 * Returns whether the given breakpoint has expired.

+	 */

+	public boolean isExpired() {

+		return getBooleanAttribute( IJavaDebugConstants.EXPIRED);

+	}	

+	

+	/**

+	 * Sets the <code>EXPIRED</code> attribute of the given breakpoint.

+	 */

+	public void setExpired(boolean expired) throws CoreException {

+		setBooleanAttribute(IJavaDebugConstants.EXPIRED, expired);	

+	}	

+	

+	/**

+	 * Returns the method the given breakpoint is installed in

+	 * or <code>null</code> if a method cannot be resolved.

+	 */

+	public IMethod getMethod() {

+		try {

+			String handle = getMethodHandleIdentifier();

+			if (handle != null) {

+				return (IMethod)JavaCore.create(handle);

+			}

+		} catch (CoreException e) {

+			logError(e);

+		}

+		return null;

+	}	

+	

+	/**

+	 * Set standard attributes of a line breakpoint

+	 */	

+	public void setLineBreakpointAttributes(String modelIdentifier, boolean enabled, int lineNumber, int charStart, int charEnd) throws CoreException {

+		Object[] values= new Object[]{getPluginIdentifier(), new Boolean(true), new Integer(lineNumber), new Integer(charStart), new Integer(charEnd)};

+		setAttributes(fgLineBreakpointAttributes, values);			

+	}

+	

+	/**

+	 * Sets the <code>TYPE_HANDLE</code> attribute of the given breakpoint, associated

+	 * with the given IType.

+	 *

+	 * If <code>hitCount > 0</code>, sets the <code>HIT_COUNT</code> attribute of the given breakpoint,

+	 * and resets the <code>EXPIRED</code> attribute to false (since, if

+	 * the hit count is changed, the breakpoint should no longer be expired).

+	 */

+	public void setTypeAndHitCount(IType type, int hitCount) throws CoreException {

+		if (hitCount == 0) {

+			setType(type);

+			return;

+		}

+		String handle = type.getHandleIdentifier();

+		Object[] values= new Object[]{handle, new Integer(hitCount), Boolean.FALSE};

+		setAttributes(fgTypeAndHitCountAttributes, values);

+	}		

+	

+	/**

+	 * Returns the <code>METHOD_HANDLE</code> attribute of the given breakpoint.

+	 */

+	public String getMethodHandleIdentifier() throws CoreException {

+		return (String)getAttribute(IJavaDebugConstants.METHOD_HANDLE);

+	}	

+	

+	/**

+	 * Returns the smallest determinable <code>IMember</code> the given breakpoint is installed in.

+	 */

+	public IMember getMember() {

+		int start = getCharStart();

+		int end = getCharEnd();

+		IType type = getBreakpointType();

+		IMember member = null;

+		if (type != null && end >= start && start >= 0) {

+			try {

+				if (type.isBinary()) {

+					member= binSearch(type.getClassFile(), type, start, end);

+				} else {

+					member= binSearch(type.getCompilationUnit(), type, start, end);

+				}

+			} catch (CoreException ce) {

+				logError(ce);

+			}

+		}

+		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 IMember binSearch(IClassFile container, IType type, int start, int end) throws JavaModelException {

+		IJavaElement je = container.getElementAt(start);

+		if (je != null && !je.equals(type)) {

+			return (IMember)je;

+		}

+		if (end > start) {

+			je = container.getElementAt(end);

+			if (je != null && !je.equals(type)) {

+				return (IMember)je;

+			}

+			int mid = ((end - start) / 2) + start;

+			if (mid > start) {

+				je = binSearch(container, type, start + 1, mid);

+				if (je == null) {

+					je = binSearch(container, type, mid + 1, end - 1);

+				}

+				return (IMember)je;

+			}

+		}

+		return null;

+	}	

+	

+	/**

+	 * Searches the given source range of the container for a member that is

+	 * not the same as the given type.

+	 */

+	protected IMember binSearch(ICompilationUnit container, IType type, int start, int end) throws JavaModelException {

+		IJavaElement je = container.getElementAt(start);

+		if (je != null && !je.equals(type)) {

+			return (IMember)je;

+		}

+		if (end > start) {

+			je = container.getElementAt(end);

+			if (je != null && !je.equals(type)) {

+				return (IMember)je;

+			}

+			int mid = ((end - start) / 2) + start;

+			if (mid > start) {

+				je = binSearch(container, type, start + 1, mid);

+				if (je == null) {

+					je = binSearch(container, type, mid + 1, end - 1);

+				}

+				return (IMember)je;

+			}

+		}

+		return null;

+	}

+	

+	/**

+	 * @see JavaBreakpoint

+	 */	

+	public String getFormattedThreadText(String threadName, String typeName, boolean systemThread) {

+		int lineNumber= getAttribute(IMarker.LINE_NUMBER, -1);

+		if (lineNumber > -1) {

+			if (systemThread) {

+				return getFormattedString(LINE_BREAKPOINT_SYS, new String[] {threadName, String.valueOf(lineNumber), typeName});

+			} else {

+				return getFormattedString(LINE_BREAKPOINT_USR, new String[] {threadName, String.valueOf(lineNumber), typeName});

+			}

+		}

+		return "";

+	}

+	

+	public String getMarkerText(boolean showQualified, String memberString) {

+		IType type= getBreakpointType();

+		if (type != null) {

+			StringBuffer label= new StringBuffer();

+			if (showQualified) {

+				label.append(type.getFullyQualifiedName());

+			} else {

+				label.append(type.getElementName());

+			}

+			int lineNumber= getLineNumber();

+			if (lineNumber > 0) {

+				label.append(" [");

+				label.append(DebugJavaUtils.getResourceString(MARKER_LABEL + LINE));

+				label.append(' ');

+				label.append(lineNumber);

+				label.append(']');

+

+			}

+			int hitCount= getHitCount();

+			if (hitCount > 0) {

+				label.append(" [");

+				label.append(DebugJavaUtils.getResourceString(MARKER_LABEL + HITCOUNT));

+				label.append(' ');

+				label.append(hitCount);

+				label.append(']');

+			}

+			if (memberString != null) {

+				label.append(" - ");

+				label.append(memberString);

+			}

+			return label.toString();

+		}

+		return "";		

+	}

+

+}

+

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/MethodEntryBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/MethodEntryBreakpoint.java
new file mode 100644
index 0000000..838dadc
--- /dev/null
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/MethodEntryBreakpoint.java
@@ -0,0 +1,231 @@
+package org.eclipse.jdt.internal.debug.core;

+

+import java.util.*;

+

+import org.eclipse.core.resources.*;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.debug.core.*;

+import org.eclipse.jdt.core.*;

+import org.eclipse.jdt.debug.core.IJavaDebugConstants;

+

+import com.sun.jdi.VMDisconnectedException;

+import com.sun.jdi.request.EventRequest;

+import com.sun.jdi.request.MethodEntryRequest;

+

+public class MethodEntryBreakpoint extends LineBreakpoint {

+	

+	static String fMarkerType= IJavaDebugConstants.JAVA_METHOD_ENTRY_BREAKPOINT;

+

+	/**

+	 * Key used to store the class name attribute pertinent to a

+	 * specific method entry request. Used for method entry breakpoints.

+	 */

+	public final static String CLASS_NAME= "className";

+	/**

+	 * Key used to store the name and signature

+	 * attribute pertinent to a specific method 

+	 * entry request breakpoint. Used for method entry breakpoints.

+	 */

+	public final static String BREAKPOINT_INFO= "breakpointInfo";

+	

+	/**

+	 * Create a method entry breakpoint on the given marker

+	 */

+	public MethodEntryBreakpoint(IMarker marker) {

+		fMarker= marker;

+	}

+	

+	/**

+	 * 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 MethodEntryBreakpoint(final IMethod method, final int hitCount) throws DebugException {

+		IWorkspaceRunnable wr= new IWorkspaceRunnable() {

+			public void run(IProgressMonitor monitor) throws CoreException {

+				// determine the resource to associate the marker with				

+				IResource resource= null;

+				resource= method.getUnderlyingResource();

+				if (resource == null) {

+					resource= method.getJavaProject().getProject();

+				}

+

+				// create the marker

+				fMarker= resource.createMarker(fMarkerType);

+				

+				// 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

+				setLineBreakpointAttributes(getPluginIdentifier(), true, -1, start, end);

+				// configure the type handle and hit count

+				setTypeAndHitCount(method.getDeclaringType(), hitCount);

+

+				// configure the method handle

+				setMethod(method);

+				

+				// configure the marker as a Java marker

+				Map attributes= getAttributes();

+				JavaCore.addJavaElementMarkerAttributes(attributes, method);

+				setAttributes(attributes);

+			}

+

+		};

+		run(wr);

+	}	

+	

+	/**

+	 * A method entry breakpoint has been added.

+     * Create or update the request.

+	 */

+	public void addToTarget(JDIDebugTarget target) {

+		IType type = getBreakpointType();

+		if (type == null) {

+//			internalError(ERROR_BREAKPOINT_NO_TYPE);

+			return;

+		}

+		String className = type.getFullyQualifiedName();

+		

+		MethodEntryRequest request = target.getMethodEntryRequest(className);

+		

+		if (request == null) {

+			try {

+				request= target.getEventRequestManager().createMethodEntryRequest();

+				request.addClassFilter(className);

+				request.putProperty(CLASS_NAME, className);

+				request.putProperty(BREAKPOINT_INFO, new ArrayList(1));

+				request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);

+				request.putProperty(IDebugConstants.BREAKPOINT_MARKER, new ArrayList(3));

+				request.putProperty(IJavaDebugConstants.HIT_COUNT, new ArrayList(3));

+			} catch (VMDisconnectedException e) {

+				return;

+			} catch (RuntimeException e) {

+				logError(e);

+				return;

+			}

+		}

+		List breakpointInfo= (List)request.getProperty(BREAKPOINT_INFO);

+		breakpointInfo.add(null);

+		

+		List breakpoints= (List)request.getProperty(IDebugConstants.BREAKPOINT);

+		breakpoints.add(this);

+		

+		

+		List hitCounts = (List)request.getProperty(IJavaDebugConstants.HIT_COUNT);

+		int hitCount = getHitCount();

+		if (hitCount > 0) {

+			hitCounts.add(new Integer(hitCount));

+		} else {

+			hitCounts.add(null);

+		}

+		completeConfiguration(request);

+		target.installBreakpoint(this, request);

+	}

+	

+	/**

+	 * A method entry breakpoint has been changed.

+	 * Update the request.

+	 */

+	public void changeForTarget(JDIDebugTarget target) {

+		MethodEntryRequest request = (MethodEntryRequest)target.getRequest(this);

+		if (request == null) {

+			return;

+		}

+		// check the enabled state

+		updateMethodEntryEnabledState(request);

+		

+		List breakpoints= (List)request.getProperty(IDebugConstants.BREAKPOINT);

+		int index= breakpoints.indexOf(this);

+		// update the breakpoints hit count

+		int newCount = getHitCount();

+		List hitCounts= (List)request.getProperty(IJavaDebugConstants.HIT_COUNT);

+		if (newCount > 0) {

+			hitCounts.set(index, new Integer(newCount));

+		} else {

+			//back to a regular breakpoint

+			hitCounts.set(index, null);			

+		}

+	}

+	

+	/**

+	 * Update the enabled state of the request associated with this

+	 * method entry breakpoint. Since a request is potentially associated

+	 * with multiple method entry breakpoints, it should be enabled if 

+	 * any of them are enabled.

+	 */

+	protected void updateMethodEntryEnabledState(MethodEntryRequest request)  {

+		IBreakpointManager manager= DebugPlugin.getDefault().getBreakpointManager();

+		Iterator breakpoints= ((List)request.getProperty(IDebugConstants.BREAKPOINT)).iterator();

+		boolean requestEnabled= false;

+		while (breakpoints.hasNext()) {

+			JavaBreakpoint breakpoint= (JavaBreakpoint)breakpoints.next();

+			if (breakpoint.isEnabled()) {

+				requestEnabled = true;

+				break;

+			}

+		}

+		updateEnabledState0(request, requestEnabled);

+	}

+	

+	/**

+	 * @see JavaBreakpoint#removeFromTarget(JDIDebugTarget)

+	 */

+	public void removeFromTarget(JDIDebugTarget target) {

+		MethodEntryRequest request = (MethodEntryRequest)target.getRequest(this);

+		if (request != null) {

+			try {

+				decrementInstallCount();

+			} catch (CoreException e) {

+				logError(e);

+			}

+			List breakpoints= (List)request.getProperty(IDebugConstants.BREAKPOINT);

+			int index = breakpoints.indexOf(this);

+			breakpoints.remove(index);

+			if (breakpoints.isEmpty()) {

+				try {

+					target.getEventRequestManager().deleteEventRequest(request); // disable & remove

+				} catch (VMDisconnectedException e) {

+				} catch (RuntimeException e) {

+					logError(e);

+				}

+			} else {

+				List hitCounts= (List)request.getProperty(IJavaDebugConstants.HIT_COUNT);

+				hitCounts.remove(index);

+			}

+		}

+	}	

+	

+	/**

+	 * Sets the <code>METHOD_HANDLE</code> attribute of this breakpoint, associated

+	 * with the given IMethod.

+	 */

+	public void setMethod(IMethod method) throws CoreException {

+		String handle = method.getHandleIdentifier();

+		setMethodHandleIdentifier(handle);

+	}

+	

+	

+	/**

+	 * Sets the <code>METHOD_HANDLE</code> attribute of this breakpoint.

+	 */

+	public void setMethodHandleIdentifier(String identifier) throws CoreException {

+		setAttribute(IJavaDebugConstants.METHOD_HANDLE, identifier);

+	}	

+

+}

+

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/RunToLineBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/RunToLineBreakpoint.java
new file mode 100644
index 0000000..0d505e8
--- /dev/null
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/RunToLineBreakpoint.java
@@ -0,0 +1,61 @@
+package org.eclipse.jdt.internal.debug.core;

+

+import org.eclipse.core.resources.IMarker;

+import org.eclipse.debug.core.DebugException;

+import org.eclipse.jdt.core.IType;

+import org.eclipse.jdt.debug.core.IJavaDebugConstants;

+

+public class RunToLineBreakpoint extends LineBreakpoint {

+	

+	// Thread label String keys

+	private static final String RUN_TO_LINE_SYS= THREAD_LABEL + "run_to_line_sys";

+	private static final String RUN_TO_LINE_USR= THREAD_LABEL + "run_to_line_usr";

+		

+	static String fMarkerType= IJavaDebugConstants.JAVA_RUN_TO_LINE_BREAKPOINT;		

+

+	/**

+	 * Create a run to line breakpoint on the given marker

+	 */

+	public RunToLineBreakpoint(IMarker marker) {

+		fMarker= marker;

+	}

+

+	/**

+	 * Creates 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.

+	 *

+	 * @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 RunToLineBreakpoint(IType type, int lineNumber, int charStart, int charEnd) throws DebugException {

+		super(type, lineNumber, charStart, charEnd, 1, fMarkerType);

+	}

+

+	/**

+	 * @see JavaBreakpoint

+	 */	

+	public String getFormattedThreadText(String threadName, String typeName, boolean systemThread) {

+		int lineNumber= getAttribute(IMarker.LINE_NUMBER, -1);

+		if (lineNumber > -1) {

+			if (systemThread) {

+				return getFormattedString(RUN_TO_LINE_SYS, new String[] {threadName, String.valueOf(lineNumber), typeName});

+			} else {

+				return getFormattedString(RUN_TO_LINE_USR, new String[] {threadName, String.valueOf(lineNumber), typeName});

+			}

+		}

+		return "";

+	}

+

+}

+

diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/Watchpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/Watchpoint.java
new file mode 100644
index 0000000..8b0a9ca
--- /dev/null
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/Watchpoint.java
@@ -0,0 +1,674 @@
+package org.eclipse.jdt.internal.debug.core;

+

+import java.text.MessageFormat;

+import java.util.List;

+import java.util.Map;

+

+import org.eclipse.core.resources.*;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.debug.core.DebugException;

+import org.eclipse.jdt.core.*;

+import org.eclipse.jdt.debug.core.IJavaDebugConstants;

+

+import com.sun.jdi.*;

+import com.sun.jdi.event.*;

+import com.sun.jdi.request.*;

+

+public class Watchpoint extends LineBreakpoint {

+	

+	// Thread label String keys

+	private static final String ACCESS_SYS= THREAD_LABEL + "access_sys";

+	private static final String ACCESS_USR= THREAD_LABEL + "access_usr";

+	private static final String MODIFICATION_SYS= THREAD_LABEL + "modification_sys";

+	private static final String MODIFICATION_USR= THREAD_LABEL + "modification_usr";

+	// Error String keys

+	private final static String PREFIX= "jdi_breakpoint.";

+	private final static String ERROR = PREFIX + "error.";	

+	private final static String ERROR_ACCESS_WATCHPOINT_NOT_SUPPORTED = ERROR + "access.not_supported";

+	private final static String ERROR_MODIFICATION_WATCHPOINT_NOT_SUPPORTED = ERROR + "modification.net_supported";

+	// Marker label String keys

+	protected final static String WATCHPOINT= MARKER_LABEL + "watchpoint.";

+	protected final static String FORMAT= WATCHPOINT + "format";	

+	protected final static String ACCESS= WATCHPOINT + "access";

+	protected final static String MODIFICATION= WATCHPOINT + "modification";

+	protected final static String BOTH= WATCHPOINT + "both";		

+

+	static String fMarkerType= IJavaDebugConstants.JAVA_WATCHPOINT;

+	

+	private final static int ACCESS_EVENT= 0;

+	private final static int MODIFICATION_EVENT= 1;

+	private int fLastEventType= -1;

+	

+	/**

+	 * Create a watchpoint for the given marker

+	 */

+	public Watchpoint(IMarker marker) {

+		super(marker);

+	}

+	

+	/**

+	 * Creates and returns a watchpoint on the

+	 * given field.

+	 * If hitCount > 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 field the field on which to suspend (on access or modification)

+	 * @param hitCount the number of times the breakpoint will be hit before

+	 * 	suspending execution - 0 if it should always suspend

+	 * @return a watchpoint

+	 * @exception DebugException if unable to create the breakpoint marker due

+	 * 	to a lower level exception

+	 */

+	public Watchpoint(final IField field) throws DebugException {

+		IWorkspaceRunnable wr= new IWorkspaceRunnable() {

+			public void run(IProgressMonitor monitor) throws CoreException {		

+				IResource resource = null;

+				ICompilationUnit compilationUnit = getCompilationUnit(field);

+				if (compilationUnit != null) {

+					resource = compilationUnit.getUnderlyingResource();

+				}

+				if (resource == null) {

+					resource = field.getJavaProject().getProject();

+				}

+				

+				if (fMarker == null) {

+					// Only create a marker if one is not already assigned

+					fMarker= resource.createMarker(fMarkerType);

+				}

+				

+				// configure the standard attributes

+				setStandardAttributes(field);

+				// configure the type handle and hit count

+				setTypeAndHitCount(field.getDeclaringType(), 0);

+				// configure the field handle

+				setField(field);

+				// configure the access and modification flags to defaults

+				setDefaultAccessAndModification();

+				setAutoDisabled(false);				

+				

+				

+				// configure the marker as a Java marker

+				Map attributes= getAttributes();

+				JavaCore.addJavaElementMarkerAttributes(attributes, field);

+				setAttributes(attributes);

+			}

+		};

+		run(wr);

+	}

+	

+	/**

+	 * @see JavaBreakpoint#installIn(JDIDebugTarget)

+	 */

+	public void addToTarget(JDIDebugTarget target) {

+		selectiveAdd(target, true, true);

+	}

+

+	/**

+	 * A single watchpoint can create multiple requests. This method provides control over this

+	 * property for explicitly choosing which requests (access, modification, or both) to 

+	 * potentially add.

+	 */	

+	protected void selectiveAdd(JDIDebugTarget target, boolean accessCheck, boolean modificationCheck) {

+		fTarget= target;

+		String topLevelName= getTopLevelTypeName();

+		if (topLevelName == null) {

+//			internalError(ERROR_BREAKPOINT_NO_TYPE);

+			return;

+		}

+		

+		List classes= target.jdiClassesByName(topLevelName);

+		if (classes == null || classes.isEmpty()) {

+			// defer

+			target.defer(this, topLevelName);

+			return;

+		}

+				

+		IField javaField= getField();

+		Field field= null;

+		ReferenceType reference= null;

+		for (int i=0; i<classes.size(); i++) {

+			reference= (ReferenceType) classes.get(i);

+			field= reference.fieldByName(javaField.getElementName());

+			if (field == null) {

+				return;

+			}

+			AccessWatchpointRequest accessRequest= null;

+			ModificationWatchpointRequest modificationRequest= null;			

+			// If we're not supposed to check access or modification, just retrieve the

+			// existing request

+			if (!accessCheck) {

+				accessRequest= target.getAccessWatchpointRequest(field);

+			}

+			if (!modificationCheck) {

+				modificationRequest= target.getModificationWatchpointRequest(field);

+			}

+			if (isAccess() && accessCheck) {

+				if (accessSupportedBy(target.getVM())) {

+					accessRequest= accessWatchpointAdded(target, field);

+				} else {

+					notSupported(ERROR_ACCESS_WATCHPOINT_NOT_SUPPORTED);				

+				}

+			}

+			if (isModification() && modificationCheck) {

+				if (modificationSupportedBy(target.getVM())) {

+					modificationRequest= modificationWatchpointAdded(target, field);

+				} else {

+					notSupported(ERROR_MODIFICATION_WATCHPOINT_NOT_SUPPORTED);

+				}

+			}

+			if (!(accessRequest == null && modificationRequest == null)) {

+				Object[] requests= {accessRequest, modificationRequest};

+				target.installBreakpoint(this, requests);

+				try {		

+					incrementInstallCount();

+				} catch (CoreException e) {

+					target.internalError(e);

+				}				

+			}

+		}

+	}

+	

+	/**

+	 * Returns whether this kind of breakpoint is supported by the given

+	 * virtual machine. A watchpoint is supported if both access and

+	 * modification watchpoints are supported.

+	 */

+	public boolean isSupportedBy(VirtualMachine vm) {

+		return (modificationSupportedBy(vm) && accessSupportedBy(vm));

+	}

+	

+	/**

+	 * Returns whether the given virtual machine supports modification watchpoints

+	 */

+	public boolean modificationSupportedBy(VirtualMachine vm) {

+		return vm.canWatchFieldModification();

+	}

+	

+	/**

+	 * Returns whether the given virtual machine supports access watchpoints

+	 */

+	public boolean accessSupportedBy(VirtualMachine vm) {

+		return vm.canWatchFieldAccess();

+	}

+	

+	/**

+	 * This watchpoint is not supported for some reason. Alert the user.

+	 */

+	protected void notSupported(String error_key) {

+	}

+	

+	/**

+	 * An access watchpoint has been added.

+	 * Create or update the request.

+	 */

+	protected AccessWatchpointRequest accessWatchpointAdded(JDIDebugTarget target, Field field) {

+		AccessWatchpointRequest request= target.getAccessWatchpointRequest(field);

+		if (request == null) {

+			request= createAccessWatchpoint(target, field);

+		}

+		// Important: Enable only after request has been configured

+		request.setEnabled(isEnabled());

+		return request;

+	}

+	

+	/**

+	 * Create an access watchpoint for the given breakpoint and associated field

+	 */

+	protected AccessWatchpointRequest createAccessWatchpoint(JDIDebugTarget target, Field field) {

+		AccessWatchpointRequest request= null;

+			try {

+				request= target.getEventRequestManager().createAccessWatchpointRequest(field);

+				configureRequest(request);

+			} catch (VMDisconnectedException e) {

+				return null;

+			} catch (RuntimeException e) {

+				target.internalError(e);

+				return null;

+			}

+		return request;

+	}	

+	

+	/**

+	 * A modification watchpoint has been added.

+	 * Create or update the request.

+	 */

+	protected ModificationWatchpointRequest modificationWatchpointAdded(JDIDebugTarget target, Field field) {

+		ModificationWatchpointRequest request= target.getModificationWatchpointRequest(field);

+		if (request == null) {

+			request= createModificationWatchpoint(target, field);

+		}

+		// Important: only enable a request after it has been configured

+		request.setEnabled(isEnabled());

+		return request;

+	}

+	

+	/**

+	 * Create a modification watchpoint for the given breakpoint and associated field

+	 */

+	protected ModificationWatchpointRequest createModificationWatchpoint(JDIDebugTarget target, Field field) {

+		ModificationWatchpointRequest request= null;

+		try {

+			request= target.getEventRequestManager().createModificationWatchpointRequest(field);

+			configureRequest(request);

+		} catch (VMDisconnectedException e) {

+			return null;

+		} catch (RuntimeException e) {

+			target.internalError(e);

+			return null;

+		}

+		return request;			

+	}		

+

+	/**

+	 * A watchpoint has been changed.

+	 * Update the request.

+	 */

+	public void changeForTarget(JDIDebugTarget target) {

+		Object[] requests= (Object[])target.getRequest(this);		

+		for (int i=0; i < requests.length; i++) {

+			WatchpointRequest request= (WatchpointRequest)requests[i];

+			if (request == null) {

+				if ((i == 0) && isAccess()) {

+					selectiveAdd(target, true, false);

+				}

+				if ((i == 1) && isModification()) {

+					selectiveAdd(target, false, true);

+				}

+				continue;

+			}

+			if ((!isAccess() && (request instanceof AccessWatchpointRequest)) ||

+			(!isModification() && (request instanceof ModificationWatchpointRequest))) {

+				target.getEventRequestManager().deleteEventRequest(request); // disable & remove

+				continue;

+			}

+			request= (WatchpointRequest)updateHitCount(request, target);

+

+			if (request != null) {

+				updateEnabledState(request);					

+				requests[i]= request;

+			}				

+		}

+	}

+

+	/**

+	 * Update the hit count of an <code>EventRequest</code>. Return a new request with

+	 * the appropriate settings.

+	 */

+	protected EventRequest updateHitCount(EventRequest request, JDIDebugTarget target) {		

+		

+		// if the hit count has changed, or the request has expired and is being re-enabled,

+		// create a new request

+		if (hasHitCountChanged(request) || (isExpired(request) && this.isEnabled())) {

+			try {

+				// delete old request

+				//on JDK you cannot delete (disable) an event request that has hit its count filter

+				if (!isExpired(request)) {

+					target.getEventRequestManager().deleteEventRequest(request); // disable & remove

+				}		

+				Field field= ((WatchpointRequest) request).field();

+				if (request instanceof AccessWatchpointRequest) {

+					request= createAccessWatchpoint(target, field);

+				} else if (request instanceof ModificationWatchpointRequest) {

+					request= createModificationWatchpoint(target, field);

+				}

+			} catch (VMDisconnectedException e) {

+			} catch (RuntimeException e) {

+				logError(e);

+			}

+		}

+		return request;

+	}

+

+	/**

+	 * @see JavaBreakpoint#removeFromTarget(JDIDebugTarget)

+	 */

+	public void removeFromTarget(JDIDebugTarget target) {

+		Object[] requests= (Object[]) target.getRequest(this);

+		if (requests == null) {

+			//deferred breakpoint

+			if (!this.exists()) {

+				//resource no longer exists

+				return;

+			}

+			String name= getTopLevelTypeName();

+			if (name == null) {

+//				internalError(ERROR_BREAKPOINT_NO_TYPE);

+				return;

+			}

+			List breakpoints= (List) target.getDeferredBreakpointsByClass(name);

+			if (breakpoints == null) {

+				return;

+			}

+

+			breakpoints.remove(this);

+			if (breakpoints.isEmpty()) {

+				target.removeDeferredBreakpointByClass(name);

+			}

+		} else {

+			//installed breakpoint

+			try {

+				for (int i=0; i<requests.length; i++) {

+					WatchpointRequest request= (WatchpointRequest)requests[i];

+					if (request == null) {

+						continue;

+					}

+					target.getEventRequestManager().deleteEventRequest(request); // disable & remove					

+				}

+				try {

+					decrementInstallCount();

+				} catch (CoreException e) {

+					fTarget= null;

+					logError(e);

+				}			

+			} catch (VMDisconnectedException e) {

+				fTarget= null;

+				return;

+			} catch (RuntimeException e) {

+				fTarget= null;

+				logError(e);

+			}

+		}

+		fTarget= null;

+	}

+

+	/**

+	 * Enable this watchpoint.

+	 * 

+	 * If the watchpoint is not watching access or modification,

+	 * set the default values. If this isn't done, the resulting

+	 * state (enabled with access and modification both disabled)

+	 * is ambiguous.

+	 */

+	public void enable() {

+		if (!(isAccess() || isModification())) {

+			setDefaultAccessAndModification();

+		}

+		super.enable();

+	}

+	

+	/**

+	 * Returns whether this watchpoint is an access watchpoint

+	 */

+	public boolean isAccess() {

+		return getAttribute(IJavaDebugConstants.ACCESS, false);

+	}

+	

+	/**

+	 * Toggle the access attribute of this watchpoint

+	 */

+	public void toggleAccess() {

+		setAccess(!isAccess());

+	}

+	

+	/**

+	 * Sets the access attribute of this watchpoint. If access is set to true

+	 * and the watchpoint is disabled, enable the watchpoint. If both access and 

+	 * modification are false, disable the watchpoint.

+	 */

+	public void setAccess(boolean access) {

+		if (access == isAccess()) {

+			return;

+		}		

+		try {

+			setAttribute(IJavaDebugConstants.ACCESS, access);

+			if (access && !isEnabled()) {

+				enable();

+			} else if (!(access || isModification())) {

+				disable();

+			}

+		} catch (CoreException ce) {

+			logError(ce);

+		}

+		if (fTarget != null) {

+			// Notify the target that this watchpoint has changed

+			changeForTarget(fTarget);

+		}

+	}

+	

+	/**

+	 * Returns whether this watchpoint is a modification watchpoint

+	 */	

+	public boolean isModification() {

+		return getAttribute(IJavaDebugConstants.MODIFICATION, false);

+	}

+	

+	/**

+	 * Toggle the modification attribute of this watchpoint

+	 */

+	public void toggleModification() {

+		setModification(!isModification());

+	}

+	

+	/**

+	 * Sets the modification attribute of this watchpoint. If modification is set to true

+	 * and the watchpoint is disabled, enable the watchpoint. If both access and 

+	 * modification are false, disable the watchpoint.

+	 */

+	public void setModification(boolean modification) {

+		if (modification == isModification()) {

+			return;

+		}

+		try {

+			setAttribute(IJavaDebugConstants.MODIFICATION, modification);

+			if (modification && !isEnabled()) {

+				enable();

+			} else if (!(modification || isAccess())) {

+				disable();

+			}

+		} catch (CoreException ce) {

+			logError(ce);

+		}

+		if (fTarget != null) {

+			// Notify the target that this watchpoint has changed

+			changeForTarget(fTarget);

+		}	

+	}

+		

+	/**

+	 * Sets the default access and modification attributes of the watchpoint.

+	 * The default values are:

+	 * <ul>

+	 * <li>access = <code>false</code>

+	 * <li>modification = <code>true</code>

+	 * <ul>

+	 */

+	public void setDefaultAccessAndModification() {

+		Object[] values= new Object[]{Boolean.FALSE, Boolean.TRUE};

+		String[] attributes= new String[]{IJavaDebugConstants.ACCESS, IJavaDebugConstants.MODIFICATION};

+		try {

+			setAttributes(attributes, values);

+		} catch (CoreException ce) {

+			logError(ce);

+		}

+	}

+

+	/**

+	 * Sets the <code>FIELD_HANDLE</code> attribute of the given breakpoint, associated

+	 * with the given IField.

+	 */

+	public void setField(IField field) throws CoreException {

+		String handle = field.getHandleIdentifier();

+		setFieldHandleIdentifier(handle);

+	}

+	

+	/**

+	 * Sets the <code>FIELD_HANDLE</code> attribute of the given breakpoint.

+	 */

+	public void setFieldHandleIdentifier(String handle) throws CoreException {

+		setAttribute(IJavaDebugConstants.FIELD_HANDLE, handle);

+	}

+	

+	/**

+	 * Set standard attributes of a watchpoint

+	 */

+	public void setStandardAttributes(IField field) throws CoreException {

+		// find the source range if available

+		int start = -1;

+		int stop = -1;

+		ISourceRange range = field.getSourceRange();

+		if (range != null) {

+			start = range.getOffset();

+			stop = start + range.getLength() - 1;

+		}

+		super.setLineBreakpointAttributes(getPluginIdentifier(), true, -1, start, stop);

+	}		

+

+	/**

+	 * Sets the <code>AUTO_DISABLED</code> attribute of the given breakpoint.

+	 */

+	public void setAutoDisabled(boolean autoDisabled) throws CoreException {

+		setAttribute(IJavaDebugConstants.AUTO_DISABLED, autoDisabled);

+	}

+

+	/**

+	 * Returns the underlying compilation unit of an element.

+	 */

+	public static ICompilationUnit getCompilationUnit(IJavaElement element) {

+		if (element instanceof IWorkingCopy) {

+			return (ICompilationUnit) ((IWorkingCopy) element).getOriginalElement();

+		}

+		if (element instanceof ICompilationUnit) {

+			return (ICompilationUnit) element;

+		}		

+		IJavaElement parent = element.getParent();

+		if (parent != null) {

+			return getCompilationUnit(parent);

+		}

+		return null;

+	}

+	

+	/**

+	 * Generate the field associated with the given marker

+	 */

+	public IField getField(IMarker marker) {

+		String handle= getFieldHandleIdentifier(marker);

+		if (handle != null && handle != "") {

+			return (IField)JavaCore.create(handle);

+		}

+		return null;

+	}	

+	

+	/**

+	 * Generate the field associated with this watchpoint

+	 */

+	public IField getField() {

+		String handle= getFieldHandleIdentifier();

+		if (handle != null && handle != "") {

+			return (IField)JavaCore.create(handle);

+		}

+		return null;

+	}		

+	

+	/**

+	 * Returns the <code>FIELD_HANDLE</code> attribute of the given marker.

+	 */

+	public String getFieldHandleIdentifier(IMarker marker) {

+		String handle;

+		try {

+			handle= (String)marker.getAttribute(IJavaDebugConstants.FIELD_HANDLE);

+		} catch (CoreException ce) {

+			handle= "";

+			logError(ce);

+		}

+		return handle;

+	}

+	

+	/**

+	 * Returns the <code>FIELD_HANDLE</code> attribute of this watchpoint.

+	 */

+	public String getFieldHandleIdentifier() {

+		String handle;

+		try {

+			handle= (String)getAttribute(IJavaDebugConstants.FIELD_HANDLE);

+		} catch (CoreException ce) {

+			handle= "";

+			logError(ce);

+		}

+		return handle;

+	}

+	

+	/**

+	 * @see JavaBreakpoint

+	 */

+	public String getFormattedThreadText(String threadName, String typeName, boolean systemThread) {

+		String fieldName= getField().getElementName();

+		if (fLastEventType == ACCESS_EVENT) {

+			if (systemThread) {

+				return getFormattedString(ACCESS_SYS, new String[] {threadName, fieldName, typeName});

+			} else {

+				return getFormattedString(ACCESS_USR, new String[] {threadName, fieldName, typeName});

+			}

+		} else if (fLastEventType == MODIFICATION_EVENT) {

+			// modification

+			if (systemThread) {

+				return getFormattedString(MODIFICATION_SYS, new String[] {threadName, fieldName, typeName});

+			} else {

+				return getFormattedString(MODIFICATION_USR, new String[] {threadName, fieldName, typeName});

+			}

+		}

+		return "";	

+	}

+	

+	public String getMarkerText(boolean qualified, String memberString) {

+		String lineInfo= super.getMarkerText(qualified, memberString);

+

+		String state= null;

+		boolean access= isAccess();

+		boolean modification= isModification();

+		if (access && modification) {

+			state= BOTH;

+		} else if (access) {

+			state= ACCESS;

+		} else if (modification) {

+			state= MODIFICATION;

+		}		

+		String label= null;

+		if (state == null) {

+			label= lineInfo;

+		} else {

+			String format= DebugJavaUtils.getResourceString(FORMAT);

+			state= DebugJavaUtils.getResourceString(state);

+			label= MessageFormat.format(format, new Object[] {state, lineInfo});

+		}

+		return label;	

+	}

+	

+	/**

+	 * Store the type of the event, then handle it as specified in

+	 * the superclass. This is useful for correctly generating the

+	 * thread text when asked (assumes thread text is requested after

+	 * the event is passed to this breakpoint.

+	 * 

+	 * Also, @see JavaBreakpoint#handleEvent(Event)

+	 */

+	public void handleEvent(Event event, JDIDebugTarget target) {

+		if (event instanceof AccessWatchpointEvent) {

+			fLastEventType= ACCESS_EVENT;

+		} else if (event instanceof ModificationWatchpointEvent) {

+			fLastEventType= MODIFICATION_EVENT;

+		}

+		super.handleEvent(event, target);

+	}	

+	

+	/**

+	 * Returns the <code>HIT_COUNT</code> attribute of the given breakpoint

+	 * or -1 if the attribute is not set.

+	 */

+	public int getHitCount() {

+		return getAttribute(IJavaDebugConstants.HIT_COUNT, -1);

+	}

+	

+	/**

+	 * Sets the <code>HIT_COUNT</code> attribute of the given breakpoint,

+	 * and resets the <code>EXPIRED</code> attribute to false (since, if

+	 * the hit count is changed, the breakpoint should no longer be expired).

+	 */

+	public void setHitCount(int count) throws CoreException {

+		setAttributes(new String[]{IJavaDebugConstants.HIT_COUNT, IJavaDebugConstants.EXPIRED},

+						new Object[]{new Integer(count), Boolean.FALSE});

+	}	

+

+}

+

diff --git a/org.eclipse.jdt.debug/plugin.xml b/org.eclipse.jdt.debug/plugin.xml
index d6cc702..fc7a07b 100644
--- a/org.eclipse.jdt.debug/plugin.xml
+++ b/org.eclipse.jdt.debug/plugin.xml
@@ -27,17 +27,30 @@
 <!-- Extensions -->

 <!-- Extension points -->

 <extension

-      id="javaLineBreakpoint"

-      point="org.eclipse.core.resources.markers">

-   <super

-         type="org.eclipse.debug.core.lineBreakpoint">

-   </super>

+	id="javaBreakpoint"

+	point="org.eclipse.core.resources.markers">

+	<super

+		type="org.eclipse.debug.core.breakpoint">	

+	</super>

    <persistent

          value="true">

    </persistent>

    <attribute

          name="typeHandle">

-   </attribute>

+	</attribute>         

+</extension>     	

+<extension

+      id="javaLineBreakpoint"

+      point="org.eclipse.core.resources.markers">

+   <super

+         type="org.eclipse.jdt.debug.javaBreakpoint">      

+   </super>         

+   <super

+         type="org.eclipse.debug.core.lineBreakpoint">

+   </super>

+   <persistent

+         value="true">

+   </persistent>   

    <attribute

          name="installCount">

    </attribute>

@@ -62,14 +75,11 @@
       id="javaExceptionBreakpoint"

       point="org.eclipse.core.resources.markers">

    <super

-         type="org.eclipse.debug.core.breakpoint">

+         type="org.eclipse.jdt.debug.javaBreakpoint">

    </super>

    <persistent

          value="true">

-   </persistent>

-   <attribute

-         name="typeHandle">

-   </attribute>

+   </persistent>   

    <attribute

          name="caught">

    </attribute>

@@ -86,9 +96,9 @@
 	<super

 		type="org.eclipse.jdt.debug.javaLineBreakpoint">

 	</super>

-	<persistent

-		value="true">

-	</persistent>

+   <persistent

+         value="true">

+   </persistent>	

 	<attribute

 		name="fieldHandle">

 	</attribute>

@@ -115,4 +125,10 @@
          name="methodHandle">

    </attribute>

 </extension>

+<extension point = "org.eclipse.debug.core.breakpoint_factories">

+<breakpoint_factory

+	    id="org.eclipse.jdt.core.JavaBreakpointFactory"

+	   	class="org.eclipse.jdt.internal.debug.core.JavaBreakpointFactory"

+   		type="org.eclipse.jdt.debug.javaBreakpoint"/>

+</extension>	   	

 </plugin>