001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.debug.core.breakpoints;
011:
012: import com.ibm.icu.text.MessageFormat;
013: import java.util.HashMap;
014: import java.util.Iterator;
015: import java.util.List;
016: import java.util.Map;
017:
018: import org.eclipse.core.resources.IResource;
019: import org.eclipse.core.resources.IWorkspaceRunnable;
020: import org.eclipse.core.runtime.CoreException;
021: import org.eclipse.core.runtime.IProgressMonitor;
022: import org.eclipse.debug.core.DebugException;
023: import org.eclipse.jdt.debug.core.IJavaDebugTarget;
024: import org.eclipse.jdt.debug.core.IJavaTargetPatternBreakpoint;
025: import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
026: import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
027:
028: import com.sun.jdi.AbsentInformationException;
029: import com.sun.jdi.ReferenceType;
030: import com.sun.jdi.VMDisconnectedException;
031: import com.sun.jdi.VirtualMachine;
032:
033: public class JavaTargetPatternBreakpoint extends JavaLineBreakpoint
034: implements IJavaTargetPatternBreakpoint {
035:
036: private static final String TARGET_PATTERN_BREAKPOINT = "org.eclipse.jdt.debug.javaTargetPatternBreakpointMarker"; //$NON-NLS-1$
037:
038: /**
039: * Table of targets to patterns
040: */
041: private HashMap fPatterns;
042:
043: public JavaTargetPatternBreakpoint() {
044: }
045:
046: /**
047: * @see JDIDebugModel#createTargetPatternBreakpoint(IResource, String, int, int, int, int, boolean, Map)
048: */
049: public JavaTargetPatternBreakpoint(IResource resource,
050: String sourceName, int lineNumber, int charStart,
051: int charEnd, int hitCount, boolean add, Map attributes)
052: throws DebugException {
053: this (resource, sourceName, lineNumber, charStart, charEnd,
054: hitCount, add, attributes, TARGET_PATTERN_BREAKPOINT);
055: }
056:
057: public JavaTargetPatternBreakpoint(final IResource resource,
058: final String sourceName, final int lineNumber,
059: final int charStart, final int charEnd, final int hitCount,
060: final boolean add, final Map attributes,
061: final String markerType) throws DebugException {
062: IWorkspaceRunnable wr = new IWorkspaceRunnable() {
063: public void run(IProgressMonitor monitor)
064: throws CoreException {
065:
066: // create the marker
067: setMarker(resource.createMarker(markerType));
068:
069: // add attributes
070: addLineBreakpointAttributes(attributes,
071: getModelIdentifier(), true, lineNumber,
072: charStart, charEnd);
073: addSourceNameAndHitCount(attributes, sourceName,
074: hitCount);
075: attributes.put(SUSPEND_POLICY, new Integer(
076: getDefaultSuspendPolicy()));
077: // set attributes
078: ensureMarker().setAttributes(attributes);
079:
080: register(add);
081: }
082: };
083: run(getMarkerRule(resource), wr);
084: }
085:
086: /**
087: * Creates the event requests to:<ul>
088: * <li>Listen to class loads related to the breakpoint</li>
089: * <li>Respond to the breakpoint being hit</li>
090: * </ul>
091: */
092: public void addToTarget(JDIDebugTarget target) throws CoreException {
093:
094: // pre-notification
095: fireAdding(target);
096:
097: String referenceTypeName = getPattern(target);
098: if (referenceTypeName == null) {
099: return;
100: }
101:
102: String classPrepareTypeName = referenceTypeName;
103: // create request to listen to class loads
104: //name may only be partially resolved
105: if (!referenceTypeName.endsWith("*")) { //$NON-NLS-1$
106: classPrepareTypeName = classPrepareTypeName + '*';
107: }
108: registerRequest(target
109: .createClassPrepareRequest(classPrepareTypeName),
110: target);
111:
112: // create breakpoint requests for each class currently loaded
113: VirtualMachine vm = target.getVM();
114: if (vm == null) {
115: target
116: .requestFailed(
117: JDIDebugBreakpointMessages.JavaTargetPatternBreakpoint_Unable_to_add_breakpoint___VM_disconnected__1,
118: null);
119: }
120: List classes = vm.allClasses();
121: if (classes != null) {
122: Iterator iter = classes.iterator();
123: String typeName = null;
124: ReferenceType type = null;
125: while (iter.hasNext()) {
126: type = (ReferenceType) iter.next();
127: typeName = type.name();
128: if (typeName != null
129: && typeName.startsWith(referenceTypeName)) {
130: createRequest(target, type);
131: }
132: }
133: }
134: }
135:
136: /**
137: * @see JavaBreakpoint#getReferenceTypeName()
138: */
139: protected String getReferenceTypeName() {
140: String name = "*"; //$NON-NLS-1$
141: try {
142: name = getSourceName();
143: } catch (CoreException ce) {
144: JDIDebugPlugin.log(ce);
145: }
146: return name;
147: }
148:
149: /**
150: * @see JavaBreakpoint#installableReferenceType(ReferenceType)
151: */
152: protected boolean installableReferenceType(ReferenceType type,
153: JDIDebugTarget target) throws CoreException {
154: // if the source name attribute is specified, check for a match with the
155: // debug attribute (if available)
156: if (getSourceName() != null) {
157: String sourceName = null;
158: try {
159: sourceName = type.sourceName();
160: } catch (AbsentInformationException e) {
161: // unable to compare
162: } catch (VMDisconnectedException e) {
163: if (!target.isAvailable()) {
164: return false;
165: }
166: target
167: .targetRequestFailed(
168: MessageFormat
169: .format(
170: JDIDebugBreakpointMessages.JavaPatternBreakpoint_exception_source_name,
171: new String[] {
172: e.toString(),
173: type.name() }),
174: e);
175: // execution will not reach this line, as
176: // #targetRequestFailed will throw an exception
177: return false;
178: } catch (RuntimeException e) {
179: target
180: .targetRequestFailed(
181: MessageFormat
182: .format(
183: JDIDebugBreakpointMessages.JavaPatternBreakpoint_exception_source_name,
184: new String[] {
185: e.toString(),
186: type.name() }),
187: e);
188: // execution will not reach this line, as
189: // #targetRequestFailed will throw an exception
190: return false;
191: }
192:
193: // if the debug attribute matches the source name, attempt installion
194: if (sourceName != null) {
195: if (!getSourceName().equalsIgnoreCase(sourceName)) {
196: return false;
197: }
198: }
199: }
200:
201: String pattern = getPattern(target);
202: String queriedType = type.name();
203: if (pattern == null || queriedType == null) {
204: return false;
205: }
206: if (queriedType.startsWith(pattern)) {
207: // query registered listeners to see if this pattern breakpoint should
208: // be installed in the given target
209: return queryInstallListeners(target, type);
210: }
211: return false;
212: }
213:
214: /**
215: * Adds the source name and hit count attributes to the given map.
216: */
217: protected void addSourceNameAndHitCount(Map attributes,
218: String sourceName, int hitCount) {
219: if (sourceName != null) {
220: attributes.put(SOURCE_NAME, sourceName);
221: }
222: if (hitCount > 0) {
223: attributes.put(HIT_COUNT, new Integer(hitCount));
224: attributes.put(EXPIRED, Boolean.FALSE);
225: }
226: }
227:
228: /**
229: * @see IJavaTargetPatternBreakpoint#getPattern(IJavaDebugTarget)
230: */
231: public String getPattern(IJavaDebugTarget target) {
232: if (fPatterns != null) {
233: return (String) fPatterns.get(target);
234: }
235: return null;
236: }
237:
238: /**
239: * @see IJavaTargetPatternBreakpoint#setPattern(IJavaDebugTarget, String)
240: */
241: public void setPattern(IJavaDebugTarget target, String pattern)
242: throws CoreException {
243: if (fPatterns == null) {
244: fPatterns = new HashMap(2);
245: }
246: // if pattern is changing then remove and re-add
247: String oldPattern = getPattern(target);
248: fPatterns.put(target, pattern);
249: if (oldPattern != null && !oldPattern.equals(pattern)) {
250: recreate((JDIDebugTarget) target);
251: fireChanged();
252: }
253: }
254:
255: /**
256: * @see IJavaTargetPatternBreakpoint#getSourceName()
257: */
258: public String getSourceName() throws CoreException {
259: return (String) ensureMarker().getAttribute(SOURCE_NAME);
260: }
261:
262: /**
263: * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#removeFromTarget(JDIDebugTarget)
264: */
265: public void removeFromTarget(JDIDebugTarget target)
266: throws CoreException {
267: fPatterns.remove(target);
268: super.removeFromTarget(target);
269: }
270: }
|