/******************************************************************************* * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.debug.core.breakpoints; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.debug.core.DebugException; import org.eclipse.jdt.debug.core.IJavaDebugTarget; import org.eclipse.jdt.debug.core.IJavaTargetPatternBreakpoint; import org.eclipse.jdt.debug.core.JDIDebugModel; import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin; import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget; import com.ibm.icu.text.MessageFormat; import com.sun.jdi.AbsentInformationException; import com.sun.jdi.ReferenceType; import com.sun.jdi.VMDisconnectedException; import com.sun.jdi.VirtualMachine; public class JavaTargetPatternBreakpoint extends JavaLineBreakpoint implements IJavaTargetPatternBreakpoint { private static final String TARGET_PATTERN_BREAKPOINT = "org.eclipse.jdt.debug.javaTargetPatternBreakpointMarker"; //$NON-NLS-1$ /** * Table of targets to patterns */ private HashMap<IJavaDebugTarget, String> fPatterns; public JavaTargetPatternBreakpoint() { } /** * @see JDIDebugModel#createTargetPatternBreakpoint(IResource, String, int, * int, int, int, boolean, Map) */ public JavaTargetPatternBreakpoint(IResource resource, String sourceName, int lineNumber, int charStart, int charEnd, int hitCount, boolean add, Map<String, Object> attributes) throws DebugException { this(resource, sourceName, lineNumber, charStart, charEnd, hitCount, add, attributes, TARGET_PATTERN_BREAKPOINT); } public JavaTargetPatternBreakpoint(final IResource resource, final String sourceName, final int lineNumber, final int charStart, final int charEnd, final int hitCount, final boolean add, final Map<String, Object> attributes, final String markerType) throws DebugException { IWorkspaceRunnable wr = new IWorkspaceRunnable() { @Override public void run(IProgressMonitor monitor) throws CoreException { // create the marker setMarker(resource.createMarker(markerType)); // add attributes addLineBreakpointAttributes(attributes, getModelIdentifier(), true, lineNumber, charStart, charEnd); addSourceNameAndHitCount(attributes, sourceName, hitCount); attributes.put(SUSPEND_POLICY, new Integer( getDefaultSuspendPolicy())); // set attributes ensureMarker().setAttributes(attributes); register(add); } }; run(getMarkerRule(resource), wr); } /** * Creates the event requests to: * <ul> * <li>Listen to class loads related to the breakpoint</li> * <li>Respond to the breakpoint being hit</li> * </ul> */ @Override public void addToTarget(JDIDebugTarget target) throws CoreException { // pre-notification fireAdding(target); String referenceTypeName = getPattern(target); if (referenceTypeName == null) { return; } String classPrepareTypeName = referenceTypeName; // create request to listen to class loads // name may only be partially resolved if (!referenceTypeName.endsWith("*")) { //$NON-NLS-1$ classPrepareTypeName = classPrepareTypeName + '*'; } registerRequest(target.createClassPrepareRequest(classPrepareTypeName), target); // create breakpoint requests for each class currently loaded VirtualMachine vm = target.getVM(); if (vm != null) { List<ReferenceType> classes = vm.allClasses(); if (classes != null) { String typeName = null; for(ReferenceType type : classes) { typeName = type.name(); if (typeName != null && typeName.startsWith(referenceTypeName)) { createRequest(target, type); } } } } else { target.requestFailed( JDIDebugBreakpointMessages.JavaTargetPatternBreakpoint_Unable_to_add_breakpoint___VM_disconnected__1, null); } } /** * @see JavaBreakpoint#getReferenceTypeName() */ protected String getReferenceTypeName() { String name = "*"; //$NON-NLS-1$ try { name = getSourceName(); } catch (CoreException ce) { JDIDebugPlugin.log(ce); } return name; } /** * @see JavaBreakpoint#installableReferenceType(ReferenceType) */ @Override protected boolean installableReferenceType(ReferenceType type, JDIDebugTarget target) throws CoreException { // if the source name attribute is specified, check for a match with the // debug attribute (if available) if (getSourceName() != null) { String sourceName = null; try { sourceName = type.sourceName(); } catch (AbsentInformationException e) { // unable to compare } catch (VMDisconnectedException e) { if (!target.isAvailable()) { return false; } target.targetRequestFailed( MessageFormat.format( JDIDebugBreakpointMessages.JavaPatternBreakpoint_exception_source_name, e.toString(), type.name()), e); // execution will not reach this line, as // #targetRequestFailed will throw an exception return false; } catch (RuntimeException e) { target.targetRequestFailed( MessageFormat.format( JDIDebugBreakpointMessages.JavaPatternBreakpoint_exception_source_name, e.toString(), type.name()), e); // execution will not reach this line, as // #targetRequestFailed will throw an exception return false; } // if the debug attribute matches the source name, attempt // installion if (sourceName != null) { if (!getSourceName().equalsIgnoreCase(sourceName)) { return false; } } } String pattern = getPattern(target); String queriedType = type.name(); if (pattern == null || queriedType == null) { return false; } if (queriedType.startsWith(pattern)) { // query registered listeners to see if this pattern breakpoint // should // be installed in the given target return queryInstallListeners(target, type); } return false; } /** * Adds the source name and hit count attributes to the given map. */ protected void addSourceNameAndHitCount(Map<String, Object> attributes, String sourceName, int hitCount) { if (sourceName != null) { attributes.put(SOURCE_NAME, sourceName); } if (hitCount > 0) { attributes.put(HIT_COUNT, new Integer(hitCount)); attributes.put(EXPIRED, Boolean.FALSE); } } /** * @see IJavaTargetPatternBreakpoint#getPattern(IJavaDebugTarget) */ @Override public String getPattern(IJavaDebugTarget target) { if (fPatterns != null) { return fPatterns.get(target); } return null; } /** * @see IJavaTargetPatternBreakpoint#setPattern(IJavaDebugTarget, String) */ @Override public void setPattern(IJavaDebugTarget target, String pattern) throws CoreException { if (fPatterns == null) { fPatterns = new HashMap<>(2); } // if pattern is changing then remove and re-add String oldPattern = getPattern(target); fPatterns.put(target, pattern); if (oldPattern != null && !oldPattern.equals(pattern)) { recreate((JDIDebugTarget) target); fireChanged(); } } /** * @see IJavaTargetPatternBreakpoint#getSourceName() */ @Override public String getSourceName() throws CoreException { return (String) ensureMarker().getAttribute(SOURCE_NAME); } /** * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#removeFromTarget(JDIDebugTarget) */ @Override public void removeFromTarget(JDIDebugTarget target) throws CoreException { fPatterns.remove(target); super.removeFromTarget(target); } }