| /******************************************************************************* |
| * Copyright (c) 2000, 2012 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.debug.core.breakpoints; |
| |
| import java.util.Iterator; |
| 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.IJavaPatternBreakpoint; |
| 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; |
| |
| @SuppressWarnings("deprecation") |
| public class JavaPatternBreakpoint extends JavaLineBreakpoint implements |
| IJavaPatternBreakpoint { |
| |
| private static final String PATTERN_BREAKPOINT = "org.eclipse.jdt.debug.javaPatternBreakpointMarker"; //$NON-NLS-1$ |
| |
| /** |
| * Breakpoint attribute storing the pattern identifier of the source file in |
| * which a breakpoint is created (value |
| * <code>"org.eclipse.jdt.debug.core.pattern"</code>). This attribute is a |
| * <code>String</code>. |
| */ |
| protected static final String PATTERN = "org.eclipse.jdt.debug.core.pattern"; //$NON-NLS-1$ |
| |
| public JavaPatternBreakpoint() { |
| } |
| |
| /** |
| * @see JDIDebugModel#createPatternBreakpoint(IResource, String, int, int, |
| * int, int, boolean, Map) |
| */ |
| public JavaPatternBreakpoint(IResource resource, String sourceName, |
| String pattern, int lineNumber, int charStart, int charEnd, |
| int hitCount, boolean add, Map<String, Object> attributes) throws DebugException { |
| this(resource, sourceName, pattern, lineNumber, charStart, charEnd, |
| hitCount, add, attributes, PATTERN_BREAKPOINT); |
| } |
| |
| public JavaPatternBreakpoint(final IResource resource, |
| final String sourceName, final String pattern, |
| 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); |
| addPatternAndHitCount(attributes, sourceName, pattern, hitCount); |
| // set attributes |
| attributes.put(SUSPEND_POLICY, new Integer( |
| getDefaultSuspendPolicy())); |
| ensureMarker().setAttributes(attributes); |
| |
| register(add); |
| } |
| }; |
| run(getMarkerRule(resource), wr); |
| } |
| |
| /** |
| * @see JavaBreakpoint#getReferenceTypeName() |
| */ |
| protected String getReferenceTypeName() { |
| String name = ""; //$NON-NLS-1$ |
| try { |
| name = getPattern(); |
| } 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 |
| // installation |
| if (sourceName != null) { |
| if (!getSourceName().equalsIgnoreCase(sourceName)) { |
| return false; |
| } |
| } |
| } |
| |
| String pattern = getPattern(); |
| 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 class name pattern and hit count attributes to the given map. |
| */ |
| protected void addPatternAndHitCount(Map<String, Object> attributes, String sourceName, |
| String pattern, int hitCount) { |
| attributes.put(PATTERN, pattern); |
| if (sourceName != null) { |
| attributes.put(SOURCE_NAME, sourceName); |
| } |
| if (hitCount > 0) { |
| attributes.put(HIT_COUNT, new Integer(hitCount)); |
| attributes.put(EXPIRED, Boolean.FALSE); |
| } |
| } |
| |
| /** |
| * @see IJavaPatternBreakpoint#getPattern() |
| */ |
| @Override |
| public String getPattern() throws CoreException { |
| return (String) ensureMarker().getAttribute(PATTERN); |
| } |
| |
| /** |
| * @see IJavaPatternBreakpoint#getSourceName() |
| */ |
| @Override |
| public String getSourceName() throws CoreException { |
| return (String) ensureMarker().getAttribute(SOURCE_NAME); |
| } |
| |
| @Override |
| protected void createRequests(JDIDebugTarget target) throws CoreException { |
| if (target.isTerminated() || shouldSkipBreakpoint()) { |
| return; |
| } |
| String referenceTypeName = getReferenceTypeName(); |
| 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) { |
| target.requestFailed( |
| JDIDebugBreakpointMessages.JavaPatternBreakpoint_Unable_to_add_breakpoint___VM_disconnected__1, |
| new VMDisconnectedException()); |
| } |
| List<ReferenceType> classes = null; |
| try { |
| classes = vm.allClasses(); |
| } catch (RuntimeException e) { |
| target.targetRequestFailed( |
| JDIDebugBreakpointMessages.JavaPatternBreakpoint_0, e); |
| } |
| if (classes != null) { |
| Iterator<ReferenceType> iter = classes.iterator(); |
| String typeName = null; |
| ReferenceType type = null; |
| while (iter.hasNext()) { |
| type = iter.next(); |
| typeName = type.name(); |
| if (typeName != null && typeName.startsWith(referenceTypeName)) { |
| createRequest(target, type); |
| } |
| } |
| } |
| } |
| } |