1 11 package org.eclipse.jdt.internal.debug.core.breakpoints; 12 13 14 import java.util.HashMap ; 15 import java.util.Map ; 16 import java.util.regex.Pattern ; 17 18 import org.eclipse.core.resources.IMarker; 19 import org.eclipse.core.resources.IResource; 20 import org.eclipse.core.resources.IWorkspaceRunnable; 21 import org.eclipse.core.runtime.CoreException; 22 import org.eclipse.core.runtime.IProgressMonitor; 23 import org.eclipse.debug.core.model.IDebugTarget; 24 import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint; 25 import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin; 26 import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget; 27 import org.eclipse.jdt.internal.debug.core.model.JDIThread; 28 29 import com.sun.jdi.ClassType; 30 import com.sun.jdi.Location; 31 import com.sun.jdi.Method; 32 import com.sun.jdi.ObjectReference; 33 import com.sun.jdi.ReferenceType; 34 import com.sun.jdi.ThreadReference; 35 import com.sun.jdi.VMDisconnectedException; 36 import com.sun.jdi.event.BreakpointEvent; 37 import com.sun.jdi.event.Event; 38 import com.sun.jdi.event.LocatableEvent; 39 import com.sun.jdi.event.MethodEntryEvent; 40 import com.sun.jdi.event.MethodExitEvent; 41 import com.sun.jdi.request.BreakpointRequest; 42 import com.sun.jdi.request.EventRequest; 43 import com.sun.jdi.request.EventRequestManager; 44 import com.sun.jdi.request.MethodEntryRequest; 45 import com.sun.jdi.request.MethodExitRequest; 46 47 public class JavaMethodBreakpoint extends JavaLineBreakpoint implements IJavaMethodBreakpoint { 48 49 private static final String JAVA_METHOD_BREAKPOINT = "org.eclipse.jdt.debug.javaMethodBreakpointMarker"; 51 57 private static final String METHOD_NAME = "org.eclipse.jdt.debug.core.methodName"; 59 65 private static final String METHOD_SIGNATURE = "org.eclipse.jdt.debug.core.methodSignature"; 67 73 private static final String ENTRY = "org.eclipse.jdt.debug.core.entry"; 75 81 private static final String EXIT = "org.eclipse.jdt.debug.core.exit"; 83 89 private static final String NATIVE = "org.eclipse.jdt.debug.core.native"; 91 94 private String fMethodName = null; 95 96 99 private String fMethodSignature = null; 100 101 105 protected static final Integer ENTRY_EVENT= new Integer (0); 106 107 111 protected static final Integer EXIT_EVENT= new Integer (1); 112 113 121 private Map fLastEventTypes= new HashMap (10); 122 123 126 private Pattern fPattern; 127 128 131 private Boolean fUsesTypePattern= null; 132 133 136 public JavaMethodBreakpoint() { 137 } 138 139 public JavaMethodBreakpoint(final IResource resource, final String typePattern, final String methodName, final String methodSignature, final boolean entry, final boolean exit, final boolean nativeOnly, final int lineNumber, final int charStart, final int charEnd, final int hitCount, final boolean register, final Map attributes) throws CoreException { 140 IWorkspaceRunnable wr= new IWorkspaceRunnable() { 141 public void run(IProgressMonitor monitor) throws CoreException { 142 setMarker(resource.createMarker(JAVA_METHOD_BREAKPOINT)); 144 145 addLineBreakpointAttributes(attributes, getModelIdentifier(), true, lineNumber, charStart, charEnd); 147 addMethodNameAndSignature(attributes, methodName, methodSignature); 148 addTypeNameAndHitCount(attributes, typePattern, hitCount); 149 attributes.put(ENTRY, Boolean.valueOf(entry)); 150 attributes.put(EXIT, Boolean.valueOf(exit)); 151 attributes.put(NATIVE, Boolean.valueOf(nativeOnly)); 152 attributes.put(SUSPEND_POLICY, new Integer (getDefaultSuspendPolicy())); 153 ensureMarker().setAttributes(attributes); 155 register(register); 156 } 157 158 }; 159 run(getMarkerRule(resource), wr); 160 String type = convertToRegularExpression(typePattern); 161 fPattern = Pattern.compile(type); 162 } 163 164 171 protected void createRequest(JDIDebugTarget target, String typePattern) throws CoreException { 172 MethodEntryRequest entryRequest= createMethodEntryRequest(target, typePattern); 173 MethodExitRequest exitRequest= createMethodExitRequest(target, typePattern); 174 175 registerRequest(entryRequest, target); 176 registerRequest(exitRequest, target); 177 } 178 179 189 protected MethodEntryRequest createMethodEntryRequest(JDIDebugTarget target, String typePattern) throws CoreException { 190 return (MethodEntryRequest)createMethodRequest(target, typePattern, true); 191 } 192 193 203 protected MethodExitRequest createMethodExitRequest(JDIDebugTarget target, String typePattern) throws CoreException { 204 return (MethodExitRequest)createMethodRequest(target, typePattern, false); 205 } 206 207 217 protected EventRequest createMethodEntryRequest(JDIDebugTarget target, ReferenceType type) throws CoreException { 218 return createMethodRequest(target, type, true); 219 } 220 221 230 protected EventRequest createMethodExitRequest(JDIDebugTarget target, ReferenceType type) throws CoreException { 231 return createMethodRequest(target, type, false); 232 } 233 234 248 private EventRequest createMethodRequest(JDIDebugTarget target, Object classFilter, boolean entry) throws CoreException { 249 EventRequest request = null; 250 EventRequestManager manager = target.getEventRequestManager(); 251 if (manager == null) { 252 target.requestFailed(JDIDebugBreakpointMessages.JavaMethodBreakpoint_Unable_to_create_breakpoint_request___VM_disconnected__1, null); 253 } 254 try { 255 if (entry) { 256 if (classFilter instanceof ClassType && getMethodName() != null && getMethodSignature() != null) { 257 ClassType clazz = (ClassType)classFilter; 259 if (clazz.name().equals(getTypeName())) { 260 Method method = clazz.concreteMethodByName(getMethodName(), getMethodSignature()); 262 if (method != null && !method.isNative()) { 263 Location location = method.location(); 264 if (location != null && location.codeIndex() != -1) { 265 request = manager.createBreakpointRequest(location); 266 } 267 } 268 } 269 } 270 if (request == null) { 271 request = manager.createMethodEntryRequest(); 272 if (classFilter instanceof String ) { 273 ((MethodEntryRequest)request).addClassFilter((String )classFilter); 274 } else if (classFilter instanceof ReferenceType) { 275 ((MethodEntryRequest)request).addClassFilter((ReferenceType)classFilter); 276 } 277 } 278 } else { 279 request= manager.createMethodExitRequest(); 280 if (classFilter instanceof String ) { 281 ((MethodExitRequest)request).addClassFilter((String )classFilter); 282 } else if (classFilter instanceof ReferenceType) { 283 ((MethodExitRequest)request).addClassFilter((ReferenceType)classFilter); 284 } 285 } 286 configureRequest(request, target); 287 } catch (VMDisconnectedException e) { 288 if (!target.isAvailable()) { 289 return null; 290 } 291 JDIDebugPlugin.log(e); 292 } catch (RuntimeException e) { 293 target.internalError(e); 294 } 295 return request; 296 } 297 298 301 protected void setRequestThreadFilter(EventRequest request, ThreadReference thread) { 302 if (request instanceof MethodEntryRequest) { 303 ((MethodEntryRequest)request).addThreadFilter(thread); 304 } else if (request instanceof MethodExitRequest){ 305 ((MethodExitRequest)request).addThreadFilter(thread); 306 } else if (request instanceof BreakpointRequest) { 307 ((BreakpointRequest)request).addThreadFilter(thread); 308 } 309 } 310 311 317 protected void configureRequestHitCount(EventRequest request) throws CoreException { 318 if (request instanceof BreakpointRequest) { 319 super.configureRequestHitCount(request); 320 } else { 321 int hitCount = getHitCount(); 322 if (hitCount > 0) { 323 request.putProperty(HIT_COUNT, new Integer (hitCount)); 324 } 325 } 326 } 327 328 331 protected void updateEnabledState(EventRequest request, JDIDebugTarget target) throws CoreException { 332 boolean enabled= isEnabled(); 333 if (request instanceof MethodEntryRequest || request instanceof BreakpointRequest) { 334 enabled= enabled && isEntry(); 335 } else if (request instanceof MethodExitRequest) { 336 enabled= enabled && isExit(); 337 } 338 339 if (enabled != request.isEnabled()) { 340 internalUpdateEnabledState(request, enabled, target); 341 } 342 } 343 344 349 private void addMethodNameAndSignature(Map attributes, String methodName, String methodSignature) { 350 if (methodName != null) { 351 attributes.put(METHOD_NAME, methodName); 352 } 353 if (methodSignature != null) { 354 attributes.put(METHOD_SIGNATURE, methodSignature); 355 } 356 fMethodName= methodName; 357 fMethodSignature= methodSignature; 358 } 359 360 363 public boolean isEntrySuspend(IDebugTarget target) { 364 Integer lastEventType= (Integer ) fLastEventTypes.get(target); 365 if (lastEventType == null) { 366 return false; 367 } 368 return lastEventType.equals(ENTRY_EVENT); 369 } 370 371 374 public boolean handleBreakpointEvent(Event event, JDIDebugTarget target, JDIThread thread) { 375 if (event instanceof MethodEntryEvent) { 376 MethodEntryEvent entryEvent= (MethodEntryEvent) event; 377 fLastEventTypes.put(target, ENTRY_EVENT); 378 return handleMethodEvent(entryEvent, entryEvent.method(), target, thread); 379 } else if (event instanceof MethodExitEvent) { 380 MethodExitEvent exitEvent= (MethodExitEvent) event; 381 fLastEventTypes.put(target, EXIT_EVENT); 382 return handleMethodEvent(exitEvent, exitEvent.method(), target, thread); 383 } else if (event instanceof BreakpointEvent) { 384 fLastEventTypes.put(target, ENTRY_EVENT); 385 return super.handleBreakpointEvent(event, target, thread); 386 } 387 return true; 388 } 389 390 397 protected boolean handleMethodEvent(LocatableEvent event, Method method, JDIDebugTarget target, JDIThread thread) { 398 try { 399 if (isNativeOnly()) { 400 if (!method.isNative()) { 401 return true; 402 } 403 } 404 405 if (getMethodName() != null) { 406 if (!method.name().equals(getMethodName())) { 407 return true; 408 } 409 } 410 411 if (getMethodSignature() != null) { 412 String sig = method.signature(); 413 if(sig.indexOf('$') > -1) { 414 sig = sig.replace('$', '.'); 415 } 416 if (!sig.equals(getMethodSignature())) { 417 return true; 418 } 419 } 420 421 if (fPattern != null) { 422 if (!fPattern.matcher(method.declaringType().name()).find()) { 423 return true; 424 } 425 } 426 427 Integer count = (Integer )event.request().getProperty(HIT_COUNT); 429 if (count != null && handleHitCount(event, count)) { 430 return true; 431 } 432 if (hasCondition()) { 434 try { 435 return handleConditionalBreakpointEvent(event, thread, target); 436 } catch (CoreException exception) { 437 return !suspendForEvent(event, thread); 439 } 440 } 441 return !suspendForEvent(event, thread); } catch (CoreException e) { 443 JDIDebugPlugin.log(e); 444 } 445 return true; 446 } 447 448 453 private boolean handleHitCount(LocatableEvent event, Integer count) { 454 int hitCount = count.intValue(); 456 if (hitCount > 0) { 457 hitCount--; 458 count = new Integer (hitCount); 459 event.request().putProperty(HIT_COUNT, count); 460 if (hitCount == 0) { 461 try { 463 setExpired(true); 466 setEnabled(false); 467 } catch (CoreException e) { 468 JDIDebugPlugin.log(e); 469 } 470 return false; 471 } 472 return true; 474 } 475 return true; 477 } 478 479 482 public String getMethodName() { 483 return fMethodName; 484 } 485 486 489 public String getMethodSignature() { 490 return fMethodSignature; 491 } 492 493 496 public boolean isEntry() throws CoreException { 497 return ensureMarker().getAttribute(ENTRY, false); 498 } 499 500 503 public boolean isExit() throws CoreException { 504 return ensureMarker().getAttribute(EXIT, false); 505 } 506 507 510 public boolean isNativeOnly() throws CoreException { 511 return ensureMarker().getAttribute(NATIVE, false); 512 } 513 514 517 public void setEntry(boolean entry) throws CoreException { 518 if (isEntry() != entry) { 519 setAttribute(ENTRY, entry); 520 if (entry && !isEnabled()) { 521 setEnabled(true); 522 } else if (!(entry || isExit())) { 523 setEnabled(false); 524 } 525 recreate(); 526 } 527 } 528 529 532 public void setExit(boolean exit) throws CoreException { 533 if (isExit() != exit) { 534 setAttribute(EXIT, exit); 535 if (exit && !isEnabled()) { 536 setEnabled(true); 537 } else if (!(exit || isEntry())) { 538 setEnabled(false); 539 } 540 recreate(); 541 } 542 } 543 544 547 public void setNativeOnly(boolean nativeOnly) throws CoreException { 548 if (isNativeOnly() != nativeOnly) { 549 setAttribute(NATIVE, nativeOnly); 550 recreate(); 551 } 552 } 553 554 559 public void setMarker(IMarker marker) throws CoreException { 560 super.setMarker(marker); 561 fMethodName = marker.getAttribute(METHOD_NAME, null); 562 fMethodSignature = marker.getAttribute(METHOD_SIGNATURE, null); 563 String typePattern= marker.getAttribute(TYPE_NAME, ""); if (typePattern != null) { 565 fPattern = Pattern.compile(convertToRegularExpression(typePattern)); 566 } 567 } 568 569 574 private String convertToRegularExpression(String stringMatcherPattern) { 575 String regex = stringMatcherPattern.replaceAll("\\.", "\\\\."); regex = regex.replaceAll("\\*", "\\.\\*"); regex = regex.replaceAll("\\$", "\\\\\\$"); return regex; 579 } 580 581 587 public void setEnabled(boolean enabled) throws CoreException { 588 if (enabled) { 589 if (!(isEntry()|| isExit())) { 590 setDefaultEntryAndExit(); 591 } 592 } 593 super.setEnabled(enabled); 594 } 595 596 604 protected void setDefaultEntryAndExit() throws CoreException { 605 Object [] values= new Object []{Boolean.TRUE, Boolean.FALSE}; 606 String [] attributes= new String []{ENTRY, EXIT}; 607 setAttributes(attributes, values); 608 } 609 610 613 public boolean supportsCondition() { 614 return true; 615 } 616 617 620 public void addToTarget(JDIDebugTarget target) throws CoreException { 621 if (usesTypePattern()) { 622 fireAdding(target); 624 625 String referenceTypeNamePattern= getTypeName(); 626 if (referenceTypeNamePattern == null) { 627 return; 628 } 629 630 createRequest(target, referenceTypeNamePattern); 631 } else { 632 super.addToTarget(target); 633 } 634 } 635 638 public void removeFromTarget(JDIDebugTarget target) throws CoreException { 639 fLastEventTypes.remove(target); 640 super.removeFromTarget(target); 641 } 642 643 648 protected boolean usesTypePattern() throws CoreException { 649 if (fUsesTypePattern == null) { 650 String name = getTypeName(); 651 fUsesTypePattern= Boolean.valueOf(name != null && (name.startsWith("*") || name.endsWith("*"))); } 653 return fUsesTypePattern.booleanValue(); 654 } 655 656 662 protected boolean createRequest(JDIDebugTarget target, ReferenceType type) throws CoreException { 663 if (!type.name().equals(getTypeName()) || shouldSkipBreakpoint()) { 664 return false; 666 } 667 EventRequest entryRequest= createMethodEntryRequest(target, type); 668 EventRequest exitRequest= createMethodExitRequest(target, type); 669 670 registerRequest(entryRequest, target); 671 registerRequest(exitRequest, target); 672 return true; 673 } 674 677 protected void setTypeName(String typeName) throws CoreException { 678 fUsesTypePattern= null; 679 super.setTypeName(typeName); 680 } 681 682 685 protected void addInstanceFilter(EventRequest request, ObjectReference object) { 686 if (request instanceof MethodEntryRequest) { 687 ((MethodEntryRequest)request).addInstanceFilter(object); 688 } else if (request instanceof MethodExitRequest) { 689 ((MethodExitRequest)request).addInstanceFilter(object); 690 } else { 691 super.addInstanceFilter(request, object); 692 } 693 } 694 } 695 | Popular Tags |