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 java.util.HashMap;
013: import java.util.Map;
014: import java.util.regex.Pattern;
015:
016: import org.eclipse.core.resources.IMarker;
017: import org.eclipse.core.resources.IResource;
018: import org.eclipse.core.resources.IWorkspaceRunnable;
019: import org.eclipse.core.runtime.CoreException;
020: import org.eclipse.core.runtime.IProgressMonitor;
021: import org.eclipse.debug.core.model.IDebugTarget;
022: import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint;
023: import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
024: import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
025: import org.eclipse.jdt.internal.debug.core.model.JDIThread;
026:
027: import com.sun.jdi.ClassType;
028: import com.sun.jdi.Location;
029: import com.sun.jdi.Method;
030: import com.sun.jdi.ObjectReference;
031: import com.sun.jdi.ReferenceType;
032: import com.sun.jdi.ThreadReference;
033: import com.sun.jdi.VMDisconnectedException;
034: import com.sun.jdi.event.BreakpointEvent;
035: import com.sun.jdi.event.Event;
036: import com.sun.jdi.event.LocatableEvent;
037: import com.sun.jdi.event.MethodEntryEvent;
038: import com.sun.jdi.event.MethodExitEvent;
039: import com.sun.jdi.request.BreakpointRequest;
040: import com.sun.jdi.request.EventRequest;
041: import com.sun.jdi.request.EventRequestManager;
042: import com.sun.jdi.request.MethodEntryRequest;
043: import com.sun.jdi.request.MethodExitRequest;
044:
045: public class JavaMethodBreakpoint extends JavaLineBreakpoint implements
046: IJavaMethodBreakpoint {
047:
048: private static final String JAVA_METHOD_BREAKPOINT = "org.eclipse.jdt.debug.javaMethodBreakpointMarker"; //$NON-NLS-1$
049:
050: /**
051: * Breakpoint attribute storing the name of the method
052: * in which a breakpoint is contained.
053: * (value <code>"org.eclipse.jdt.debug.core.methodName"</code>).
054: * This attribute is a <code>String</code>.
055: */
056: private static final String METHOD_NAME = "org.eclipse.jdt.debug.core.methodName"; //$NON-NLS-1$
057:
058: /**
059: * Breakpoint attribute storing the signature of the method
060: * in which a breakpoint is contained.
061: * (value <code>"org.eclipse.jdt.debug.core.methodSignature"</code>).
062: * This attribute is a <code>String</code>.
063: */
064: private static final String METHOD_SIGNATURE = "org.eclipse.jdt.debug.core.methodSignature"; //$NON-NLS-1$
065:
066: /**
067: * Breakpoint attribute storing whether this breakpoint
068: * is an entry breakpoint.
069: * (value <code>"org.eclipse.jdt.debug.core.entry"</code>).
070: * This attribute is a <code>boolean</code>.
071: */
072: private static final String ENTRY = "org.eclipse.jdt.debug.core.entry"; //$NON-NLS-1$
073:
074: /**
075: * Breakpoint attribute storing whether this breakpoint
076: * is an exit breakpoint.
077: * (value <code>"org.eclipse.jdt.debug.core.exit"</code>).
078: * This attribute is a <code>boolean</code>.
079: */
080: private static final String EXIT = "org.eclipse.jdt.debug.core.exit"; //$NON-NLS-1$
081:
082: /**
083: * Breakpoint attribute storing whether this breakpoint
084: * only applies to native methods.
085: * (value <code>"org.eclipse.jdt.debug.core.native"</code>).
086: * This attribute is a <code>boolean</code>.
087: */
088: private static final String NATIVE = "org.eclipse.jdt.debug.core.native"; //$NON-NLS-1$
089:
090: /**
091: * Cache of method name attribute
092: */
093: private String fMethodName = null;
094:
095: /**
096: * Cache of method signature attribute
097: */
098: private String fMethodSignature = null;
099:
100: /**
101: * Flag indicating that this breakpoint last suspended execution
102: * due to a method entry
103: */
104: protected static final Integer ENTRY_EVENT = new Integer(0);
105:
106: /**
107: * Flag indicating that this breakpoint last suspended execution
108: * due to a method exit
109: */
110: protected static final Integer EXIT_EVENT = new Integer(1);
111:
112: /**
113: * Maps each debug target that is suspended for this breakpoint to reason that
114: * this breakpoint suspended it. Reasons include:
115: * <ol>
116: * <li>Method entry (value <code>ENTRY_EVENT</code>)</li>
117: * <li>Method exit (value <code>EXIT_EVENT</code>)</li>
118: * </ol>
119: */
120: private Map fLastEventTypes = new HashMap(10);
121:
122: /**
123: * Used to match type names
124: */
125: private Pattern fPattern;
126:
127: /**
128: * Cache of whether this breakpoint uses a type name pattern
129: */
130: private Boolean fUsesTypePattern = null;
131:
132: /**
133: * Constructs a new unconfigured method breakpoint
134: */
135: public JavaMethodBreakpoint() {
136: }
137:
138: public JavaMethodBreakpoint(final IResource resource,
139: final String typePattern, final String methodName,
140: final String methodSignature, final boolean entry,
141: final boolean exit, final boolean nativeOnly,
142: final int lineNumber, final int charStart,
143: final int charEnd, final int hitCount,
144: final boolean register, final Map attributes)
145: throws CoreException {
146: IWorkspaceRunnable wr = new IWorkspaceRunnable() {
147: public void run(IProgressMonitor monitor)
148: throws CoreException {
149: // create the marker
150: setMarker(resource.createMarker(JAVA_METHOD_BREAKPOINT));
151:
152: // add attributes
153: addLineBreakpointAttributes(attributes,
154: getModelIdentifier(), true, lineNumber,
155: charStart, charEnd);
156: addMethodNameAndSignature(attributes, methodName,
157: methodSignature);
158: addTypeNameAndHitCount(attributes, typePattern,
159: hitCount);
160: attributes.put(ENTRY, Boolean.valueOf(entry));
161: attributes.put(EXIT, Boolean.valueOf(exit));
162: attributes.put(NATIVE, Boolean.valueOf(nativeOnly));
163: attributes.put(SUSPEND_POLICY, new Integer(
164: getDefaultSuspendPolicy()));
165: //set attributes
166: ensureMarker().setAttributes(attributes);
167: register(register);
168: }
169:
170: };
171: run(getMarkerRule(resource), wr);
172: String type = convertToRegularExpression(typePattern);
173: fPattern = Pattern.compile(type);
174: }
175:
176: /**
177: * Creates and installs an entry and exit requests
178: * in the given type name, configuring the requests as appropriate
179: * for this breakpoint. The requests are then enabled based on whether
180: * this breakpoint is an entry breakpoint, exit breakpoint, or
181: * both. Finally, the requests are registered with the given target.
182: */
183: protected void createRequest(JDIDebugTarget target,
184: String typePattern) throws CoreException {
185: MethodEntryRequest entryRequest = createMethodEntryRequest(
186: target, typePattern);
187: MethodExitRequest exitRequest = createMethodExitRequest(target,
188: typePattern);
189:
190: registerRequest(entryRequest, target);
191: registerRequest(exitRequest, target);
192: }
193:
194: /**
195: * Returns a new method entry request for this breakpoint's
196: * criteria
197: *
198: * @param the target in which to create the request
199: * @param type the type on which to create the request
200: * @return method entry request
201: * @exception CoreException if an exception occurs accessing
202: * this breakpoint's underlying marker
203: */
204: protected MethodEntryRequest createMethodEntryRequest(
205: JDIDebugTarget target, String typePattern)
206: throws CoreException {
207: return (MethodEntryRequest) createMethodRequest(target,
208: typePattern, true);
209: }
210:
211: /**
212: * Returns a new method exit request for this breakpoint's
213: * criteria
214: *
215: * @param target the target in which to create the request
216: * @param type the type on which to create the request
217: * @return method exit request
218: * @exception CoreException if an exception occurs accessing
219: * this breakpoint's underlying marker
220: */
221: protected MethodExitRequest createMethodExitRequest(
222: JDIDebugTarget target, String typePattern)
223: throws CoreException {
224: return (MethodExitRequest) createMethodRequest(target,
225: typePattern, false);
226: }
227:
228: /**
229: * Returns a new method entry request for this breakpoint's
230: * criteria
231: *
232: * @param the target in which to create the request
233: * @param type the type on which to create the request
234: * @return method entry request
235: * @exception CoreException if an exception occurs accessing
236: * this breakpoint's underlying marker
237: */
238: protected EventRequest createMethodEntryRequest(
239: JDIDebugTarget target, ReferenceType type)
240: throws CoreException {
241: return createMethodRequest(target, type, true);
242: }
243:
244: /**
245: * Returns a new method exit request for the given reference type
246: *
247: * @param target the target in which to create the request
248: * @param type the type on which to create the request
249: * @return method exit request
250: * @exception CoreException if an exception occurs accessing
251: * this breakpoint's underlying marker
252: */
253: protected EventRequest createMethodExitRequest(
254: JDIDebugTarget target, ReferenceType type)
255: throws CoreException {
256: return createMethodRequest(target, type, false);
257: }
258:
259: /**
260: * @see JavaMethodBreakpoint#createMethodEntryRequest(JDIDebugTarget, ReferenceType)
261: * or JavaMethodBreakpoint#createMethodExitRequest(JDIDebugTarget, ReferenceType)
262: *
263: * Returns a <code>MethodEntryRequest</code> or <code>BreakpointRequest</code>
264: * if entry is <code>true</code>, a <code>MethodExitRequest</code> if entry is
265: * <code>false</code>.
266: *
267: * @param target the debug target in which to create the request
268: * @param classFilter a filter which specifies the scope of the method request. This parameter must
269: * be either a <code>String</code> or a <code>ReferenceType</code>
270: * @param entry whether or not the request will be a method entry request. If <code>false</code>,
271: * the request will be a method exit request.
272: */
273: private EventRequest createMethodRequest(JDIDebugTarget target,
274: Object classFilter, boolean entry) throws CoreException {
275: EventRequest request = null;
276: EventRequestManager manager = target.getEventRequestManager();
277: if (manager == null) {
278: target
279: .requestFailed(
280: JDIDebugBreakpointMessages.JavaMethodBreakpoint_Unable_to_create_breakpoint_request___VM_disconnected__1,
281: null);
282: }
283: try {
284: if (entry) {
285: if (classFilter instanceof ClassType
286: && getMethodName() != null
287: && getMethodSignature() != null) {
288: // use a line breakpoint if possible for better performance
289: ClassType clazz = (ClassType) classFilter;
290: if (clazz.name().equals(getTypeName())) {
291: // only use line breakpoint when there is an exact match
292: Method method = clazz.concreteMethodByName(
293: getMethodName(), getMethodSignature());
294: if (method != null && !method.isNative()) {
295: Location location = method.location();
296: if (location != null
297: && location.codeIndex() != -1) {
298: request = manager
299: .createBreakpointRequest(location);
300: }
301: }
302: }
303: }
304: if (request == null) {
305: request = manager.createMethodEntryRequest();
306: if (classFilter instanceof String) {
307: ((MethodEntryRequest) request)
308: .addClassFilter((String) classFilter);
309: } else if (classFilter instanceof ReferenceType) {
310: ((MethodEntryRequest) request)
311: .addClassFilter((ReferenceType) classFilter);
312: }
313: }
314: } else {
315: request = manager.createMethodExitRequest();
316: if (classFilter instanceof String) {
317: ((MethodExitRequest) request)
318: .addClassFilter((String) classFilter);
319: } else if (classFilter instanceof ReferenceType) {
320: ((MethodExitRequest) request)
321: .addClassFilter((ReferenceType) classFilter);
322: }
323: }
324: configureRequest(request, target);
325: } catch (VMDisconnectedException e) {
326: if (!target.isAvailable()) {
327: return null;
328: }
329: JDIDebugPlugin.log(e);
330: } catch (RuntimeException e) {
331: target.internalError(e);
332: }
333: return request;
334: }
335:
336: /**
337: * @see JavaBreakpoint#setRequestThreadFilter(EventRequest)
338: */
339: protected void setRequestThreadFilter(EventRequest request,
340: ThreadReference thread) {
341: if (request instanceof MethodEntryRequest) {
342: ((MethodEntryRequest) request).addThreadFilter(thread);
343: } else if (request instanceof MethodExitRequest) {
344: ((MethodExitRequest) request).addThreadFilter(thread);
345: } else if (request instanceof BreakpointRequest) {
346: ((BreakpointRequest) request).addThreadFilter(thread);
347: }
348: }
349:
350: /**
351: * Configure the given request's hit count. Since method
352: * entry/exit requests do not support hit counts, we simulate
353: * a hit count by manually updating a counter stored on the
354: * request.
355: */
356: protected void configureRequestHitCount(EventRequest request)
357: throws CoreException {
358: if (request instanceof BreakpointRequest) {
359: super .configureRequestHitCount(request);
360: } else {
361: int hitCount = getHitCount();
362: if (hitCount > 0) {
363: request.putProperty(HIT_COUNT, new Integer(hitCount));
364: }
365: }
366: }
367:
368: /**
369: * @see JavaBreakpoint#updateEnabledState(EventRequest, JDIDebugTarget)
370: */
371: protected void updateEnabledState(EventRequest request,
372: JDIDebugTarget target) throws CoreException {
373: boolean enabled = isEnabled();
374: if (request instanceof MethodEntryRequest
375: || request instanceof BreakpointRequest) {
376: enabled = enabled && isEntry();
377: } else if (request instanceof MethodExitRequest) {
378: enabled = enabled && isExit();
379: }
380:
381: if (enabled != request.isEnabled()) {
382: internalUpdateEnabledState(request, enabled, target);
383: }
384: }
385:
386: /**
387: * Adds the method name and signature attributes to the
388: * given attribute map, and intializes the local cache
389: * of method name and signature.
390: */
391: private void addMethodNameAndSignature(Map attributes,
392: String methodName, String methodSignature) {
393: if (methodName != null) {
394: attributes.put(METHOD_NAME, methodName);
395: }
396: if (methodSignature != null) {
397: attributes.put(METHOD_SIGNATURE, methodSignature);
398: }
399: fMethodName = methodName;
400: fMethodSignature = methodSignature;
401: }
402:
403: /**
404: * @see IJavaMethodBreakpoint#isEntrySuspend(IDebugTarget)
405: */
406: public boolean isEntrySuspend(IDebugTarget target) {
407: Integer lastEventType = (Integer) fLastEventTypes.get(target);
408: if (lastEventType == null) {
409: return false;
410: }
411: return lastEventType.equals(ENTRY_EVENT);
412: }
413:
414: /**
415: * @see JavaBreakpoint#handleBreakpointEvent(Event, JDIDebugTarget, JDIThread)
416: */
417: public boolean handleBreakpointEvent(Event event,
418: JDIDebugTarget target, JDIThread thread) {
419: if (event instanceof MethodEntryEvent) {
420: MethodEntryEvent entryEvent = (MethodEntryEvent) event;
421: fLastEventTypes.put(target, ENTRY_EVENT);
422: return handleMethodEvent(entryEvent, entryEvent.method(),
423: target, thread);
424: } else if (event instanceof MethodExitEvent) {
425: MethodExitEvent exitEvent = (MethodExitEvent) event;
426: fLastEventTypes.put(target, EXIT_EVENT);
427: return handleMethodEvent(exitEvent, exitEvent.method(),
428: target, thread);
429: } else if (event instanceof BreakpointEvent) {
430: fLastEventTypes.put(target, ENTRY_EVENT);
431: return super .handleBreakpointEvent(event, target, thread);
432: }
433: return true;
434: }
435:
436: /**
437: * Method entry/exit events are fired each time any method is invoked in a class
438: * in which a method entry/exit breakpoint has been installed.
439: * When a method entry/exit event is received by this breakpoint, ensure that
440: * the event has been fired by a method invocation that this breakpoint
441: * is interested in. If it is not, do nothing.
442: */
443: protected boolean handleMethodEvent(LocatableEvent event,
444: Method method, JDIDebugTarget target, JDIThread thread) {
445: try {
446: if (isNativeOnly()) {
447: if (!method.isNative()) {
448: return true;
449: }
450: }
451:
452: if (getMethodName() != null) {
453: if (!method.name().equals(getMethodName())) {
454: return true;
455: }
456: }
457:
458: if (getMethodSignature() != null) {
459: String sig = method.signature();
460: if (sig.indexOf('$') > -1) {
461: sig = sig.replace('$', '.');
462: }
463: if (!sig.equals(getMethodSignature())) {
464: return true;
465: }
466: }
467:
468: if (fPattern != null) {
469: if (!fPattern.matcher(method.declaringType().name())
470: .find()) {
471: return true;
472: }
473: }
474:
475: // simulate hit count
476: Integer count = (Integer) event.request().getProperty(
477: HIT_COUNT);
478: if (count != null && handleHitCount(event, count)) {
479: return true;
480: }
481: // no hit count
482: if (hasCondition()) {
483: try {
484: return handleConditionalBreakpointEvent(event,
485: thread, target);
486: } catch (CoreException exception) {
487: // log error
488: return !suspendForEvent(event, thread);
489: }
490: }
491: return !suspendForEvent(event, thread); // Resume if suspend fails
492: } catch (CoreException e) {
493: JDIDebugPlugin.log(e);
494: }
495: return true;
496: }
497:
498: /**
499: * Method breakpoints simulate hit count.
500: * When a method event is received, decrement the hit count
501: * property on the request and suspend if the hit count reaches 0.
502: */
503: private boolean handleHitCount(LocatableEvent event, Integer count) {
504: // decrement count and suspend if 0
505: int hitCount = count.intValue();
506: if (hitCount > 0) {
507: hitCount--;
508: count = new Integer(hitCount);
509: event.request().putProperty(HIT_COUNT, count);
510: if (hitCount == 0) {
511: // the count has reached 0, breakpoint hit
512: try {
513: // make a note that we auto-disabled the breakpoint
514: // order is important here...see methodEntryChanged
515: setExpired(true);
516: setEnabled(false);
517: } catch (CoreException e) {
518: JDIDebugPlugin.log(e);
519: }
520: return false;
521: }
522: // count still > 0, keep running
523: return true;
524: }
525: // hit count expired, keep running
526: return true;
527: }
528:
529: /* (non-Javadoc)
530: * @see org.eclipse.jdt.debug.core.IJavaMethodEntryBreakpoint#getMethodName()
531: */
532: public String getMethodName() {
533: return fMethodName;
534: }
535:
536: /* (non-Javadoc)
537: * @see org.eclipse.jdt.debug.core.IJavaMethodEntryBreakpoint#getMethodSignature()
538: */
539: public String getMethodSignature() {
540: return fMethodSignature;
541: }
542:
543: /**
544: * @see IJavaMethodBreakpoint#isEntry()
545: */
546: public boolean isEntry() throws CoreException {
547: return ensureMarker().getAttribute(ENTRY, false);
548: }
549:
550: /**
551: * @see IJavaMethodBreakpoint#isExit()
552: */
553: public boolean isExit() throws CoreException {
554: return ensureMarker().getAttribute(EXIT, false);
555: }
556:
557: /**
558: * @see IJavaMethodBreakpoint#isNative()
559: */
560: public boolean isNativeOnly() throws CoreException {
561: return ensureMarker().getAttribute(NATIVE, false);
562: }
563:
564: /**
565: * @see IJavaMethodBreakpoint#setEntry(boolean)
566: */
567: public void setEntry(boolean entry) throws CoreException {
568: if (isEntry() != entry) {
569: setAttribute(ENTRY, entry);
570: if (entry && !isEnabled()) {
571: setEnabled(true);
572: } else if (!(entry || isExit())) {
573: setEnabled(false);
574: }
575: recreate();
576: }
577: }
578:
579: /**
580: * @see IJavaMethodBreakpoint#setExit(boolean)
581: */
582: public void setExit(boolean exit) throws CoreException {
583: if (isExit() != exit) {
584: setAttribute(EXIT, exit);
585: if (exit && !isEnabled()) {
586: setEnabled(true);
587: } else if (!(exit || isEntry())) {
588: setEnabled(false);
589: }
590: recreate();
591: }
592: }
593:
594: /**
595: * @see IJavaMethodBreakpoint#setNativeOnly(boolean)
596: */
597: public void setNativeOnly(boolean nativeOnly) throws CoreException {
598: if (isNativeOnly() != nativeOnly) {
599: setAttribute(NATIVE, nativeOnly);
600: recreate();
601: }
602: }
603:
604: /**
605: * Initialize cache of attributes
606: *
607: * @see org.eclipse.debug.core.model.IBreakpoint#setMarker(IMarker)
608: */
609: public void setMarker(IMarker marker) throws CoreException {
610: super .setMarker(marker);
611: fMethodName = marker.getAttribute(METHOD_NAME, null);
612: fMethodSignature = marker.getAttribute(METHOD_SIGNATURE, null);
613: String typePattern = marker.getAttribute(TYPE_NAME, ""); //$NON-NLS-1$
614: if (typePattern != null) {
615: fPattern = Pattern
616: .compile(convertToRegularExpression(typePattern));
617: }
618: }
619:
620: /**
621: * converts the specified string to one which has been formated to our needs
622: * @param stringMatcherPattern the initial pattern
623: * @return the modified pattern
624: */
625: private String convertToRegularExpression(
626: String stringMatcherPattern) {
627: String regex = stringMatcherPattern.replaceAll("\\.", "\\\\."); //$NON-NLS-1$//$NON-NLS-2$
628: regex = regex.replaceAll("\\*", "\\.\\*"); //$NON-NLS-1$//$NON-NLS-2$
629: regex = regex.replaceAll("\\$", "\\\\\\$"); //$NON-NLS-1$ //$NON-NLS-2$
630: return regex;
631: }
632:
633: /**
634: * If this breakpoint is not entry or exit enabled,
635: * set the default (entry)
636: *
637: * @see org.eclipse.debug.core.model.IBreakpoint#setEnabled(boolean)
638: */
639: public void setEnabled(boolean enabled) throws CoreException {
640: if (enabled) {
641: if (!(isEntry() || isExit())) {
642: setDefaultEntryAndExit();
643: }
644: }
645: super .setEnabled(enabled);
646: }
647:
648: /**
649: * Sets the default entry and exit attributes of the method breakpoint
650: * The default values are:
651: * <ul>
652: * <li>entry = <code>true</code>
653: * <li>exit = <code>false</code>
654: * <ul>
655: */
656: protected void setDefaultEntryAndExit() throws CoreException {
657: Object[] values = new Object[] { Boolean.TRUE, Boolean.FALSE };
658: String[] attributes = new String[] { ENTRY, EXIT };
659: setAttributes(attributes, values);
660: }
661:
662: /* (non-Javadoc)
663: * @see org.eclipse.jdt.debug.core.IJavaLineBreakpoint#supportsCondition()
664: */
665: public boolean supportsCondition() {
666: return true;
667: }
668:
669: /**
670: * @see JavaBreakpoint#addToTarget(JDIDebugTarget)
671: */
672: public void addToTarget(JDIDebugTarget target) throws CoreException {
673: if (usesTypePattern()) {
674: // pre-notification
675: fireAdding(target);
676:
677: String referenceTypeNamePattern = getTypeName();
678: if (referenceTypeNamePattern == null) {
679: return;
680: }
681:
682: createRequest(target, referenceTypeNamePattern);
683: } else {
684: super .addToTarget(target);
685: }
686: }
687:
688: /**
689: * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#removeFromTarget(JDIDebugTarget)
690: */
691: public void removeFromTarget(JDIDebugTarget target)
692: throws CoreException {
693: fLastEventTypes.remove(target);
694: super .removeFromTarget(target);
695: }
696:
697: /**
698: * Returns whether this breakpoint uses type name pattern matching.
699: *
700: * @return whether this breakpoint uses type name pattern matching
701: */
702: protected boolean usesTypePattern() throws CoreException {
703: if (fUsesTypePattern == null) {
704: String name = getTypeName();
705: fUsesTypePattern = Boolean.valueOf(name != null
706: && (name.startsWith("*") || name.endsWith("*"))); //$NON-NLS-1$ //$NON-NLS-2$
707: }
708: return fUsesTypePattern.booleanValue();
709: }
710:
711: /**
712: * Used when this breakpoint is for a specific type (i.e. not using type name
713: * pattern matching).
714: *
715: * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#createRequest(JDIDebugTarget, ReferenceType)
716: */
717: protected boolean createRequest(JDIDebugTarget target,
718: ReferenceType type) throws CoreException {
719: if (!type.name().equals(getTypeName())
720: || shouldSkipBreakpoint()) {
721: // do not create requests for inner/outer types if this is for a specific type
722: return false;
723: }
724: EventRequest entryRequest = createMethodEntryRequest(target,
725: type);
726: EventRequest exitRequest = createMethodExitRequest(target, type);
727:
728: registerRequest(entryRequest, target);
729: registerRequest(exitRequest, target);
730: return true;
731: }
732:
733: /**
734: * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#setTypeName(String)
735: */
736: protected void setTypeName(String typeName) throws CoreException {
737: fUsesTypePattern = null;
738: super .setTypeName(typeName);
739: }
740:
741: /**
742: * @see org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint#addInstanceFilter(EventRequest, ObjectReference)
743: */
744: protected void addInstanceFilter(EventRequest request,
745: ObjectReference object) {
746: if (request instanceof MethodEntryRequest) {
747: ((MethodEntryRequest) request).addInstanceFilter(object);
748: } else if (request instanceof MethodExitRequest) {
749: ((MethodExitRequest) request).addInstanceFilter(object);
750: } else {
751: super.addInstanceFilter(request, object);
752: }
753: }
754: }
|