001: package org.drools.eclipse.debug.core;
002:
003: import java.text.MessageFormat;
004: import java.util.ArrayList;
005: import java.util.Iterator;
006: import java.util.List;
007:
008: import org.drools.eclipse.DroolsEclipsePlugin;
009: import org.drools.rule.builder.dialect.mvel.MVELDialect;
010: import org.eclipse.core.resources.IMarkerDelta;
011: import org.eclipse.core.runtime.CoreException;
012: import org.eclipse.debug.core.DebugEvent;
013: import org.eclipse.debug.core.DebugException;
014: import org.eclipse.debug.core.ILaunch;
015: import org.eclipse.debug.core.model.IBreakpoint;
016: import org.eclipse.debug.core.model.IProcess;
017: import org.eclipse.debug.core.model.IThread;
018: import org.eclipse.jdi.TimeoutException;
019: import org.eclipse.jdt.debug.core.IJavaBreakpoint;
020: import org.eclipse.jdt.internal.debug.core.IJDIEventListener;
021: import org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint;
022: import org.eclipse.jdt.internal.debug.core.model.JDIDebugModelMessages;
023: import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
024: import org.eclipse.jdt.internal.debug.core.model.JDIObjectValue;
025: import org.eclipse.jdt.internal.debug.core.model.JDIThread;
026:
027: import com.sun.jdi.ClassType;
028: import com.sun.jdi.IntegerValue;
029: import com.sun.jdi.Method;
030: import com.sun.jdi.ObjectCollectedException;
031: import com.sun.jdi.ObjectReference;
032: import com.sun.jdi.ReferenceType;
033: import com.sun.jdi.StringReference;
034: import com.sun.jdi.ThreadReference;
035: import com.sun.jdi.VMDisconnectedException;
036: import com.sun.jdi.VirtualMachine;
037: import com.sun.jdi.event.ClassPrepareEvent;
038: import com.sun.jdi.event.Event;
039: import com.sun.jdi.event.MethodEntryEvent;
040: import com.sun.jdi.event.ThreadDeathEvent;
041: import com.sun.jdi.event.ThreadStartEvent;
042: import com.sun.jdi.event.VMStartEvent;
043: import com.sun.jdi.request.ClassPrepareRequest;
044: import com.sun.jdi.request.EventRequest;
045: import com.sun.jdi.request.EventRequestManager;
046: import com.sun.jdi.request.MethodEntryRequest;
047:
048: public class DroolsDebugTarget extends JDIDebugTarget {
049:
050: private ArrayList fThreads;
051: private ThreadStartHandler fThreadStartHandler = null;
052: private boolean fSuspended = true;
053:
054: public DroolsDebugTarget(ILaunch launch, VirtualMachine jvm,
055: String name, boolean supportTerminate,
056: boolean supportDisconnect, IProcess process, boolean resume) {
057: super (launch, jvm, name, supportTerminate, supportDisconnect,
058: process, resume);
059: }
060:
061: public void breakpointAdded(IBreakpoint breakpoint) {
062:
063: try {
064: if (breakpoint instanceof DroolsLineBreakpoint) {
065: ((DroolsLineBreakpoint) breakpoint)
066: .setJavaBreakpointProperties();
067:
068: final DroolsLineBreakpoint d = (DroolsLineBreakpoint) breakpoint;
069:
070: if (d.getDialectName().equals(MVELDialect.ID)) {
071: //getBreakpoints().add( breakpoint );
072: //super.breakpointAdded(breakpoint);
073:
074: Iterator handleriter = getVM().classesByName(
075: "org.drools.base.mvel.MVELDebugHandler")
076: .iterator();
077: if (!handleriter.hasNext()) {
078: // Create class prepare request to add breakpoint after MVELDebugHanlder is loaded
079: ClassPrepareRequest req = getEventRequestManager()
080: .createClassPrepareRequest();
081: req
082: .addClassFilter("org.drools.base.mvel.MVELDebugHandler");
083: req.setSuspendPolicy(EventRequest.SUSPEND_ALL);
084:
085: addJDIEventListener(new IJDIEventListener() {
086:
087: public boolean handleEvent(Event event,
088: JDIDebugTarget target) {
089: addRemoteBreakpoint(d);
090: return true;
091: }
092:
093: public void wonSuspendVote(Event event,
094: JDIDebugTarget target) {
095: }
096:
097: }, req);
098:
099: req.enable();
100: return;
101: }
102:
103: addRemoteBreakpoint(d);
104: } else {
105: // only add breakpoint if setting Java properties of DRL
106: // breakpoint does not generate an error
107: super .breakpointAdded(breakpoint);
108: }
109: } else {
110: super .breakpointAdded(breakpoint);
111: }
112: } catch (Throwable t) {
113: // Exception will be thrown when trying to use breakpoint
114: // on drl that is incorrect (cannot be parsed or compiled)
115: DroolsEclipsePlugin.log(t);
116: }
117: }
118:
119: protected synchronized void initialize() {
120: setThreadList(new ArrayList(5));
121: super .initialize();
122: }
123:
124: protected JDIThread createThread(ThreadReference thread) {
125: JDIThread jdiThread = null;
126: try {
127: jdiThread = new DroolsThread(this , thread);
128: } catch (ObjectCollectedException exception) {
129: // ObjectCollectionException can be thrown if the thread has already
130: // completed (exited) in the VM.
131: return null;
132: }
133: if (isDisconnected()) {
134: return null;
135: }
136: synchronized (fThreads) {
137: fThreads.add(jdiThread);
138: }
139: jdiThread.fireCreationEvent();
140: return jdiThread;
141: }
142:
143: private Iterator getThreadIterator() {
144: List threadList;
145: synchronized (fThreads) {
146: threadList = (List) fThreads.clone();
147: }
148: return threadList.iterator();
149: }
150:
151: private boolean hasSuspendedThreads() {
152: Iterator it = getThreadIterator();
153: while (it.hasNext()) {
154: IThread thread = (IThread) it.next();
155: if (thread.isSuspended())
156: return true;
157: }
158: return false;
159: }
160:
161: public boolean canResume() {
162: return (isSuspended() || hasSuspendedThreads())
163: && isAvailable() && !isPerformingHotCodeReplace();
164: }
165:
166: protected void resume(boolean fireNotification)
167: throws DebugException {
168: if ((!isSuspended() && !hasSuspendedThreads())
169: || !isAvailable()) {
170: return;
171: }
172: try {
173: setSuspended(false);
174: resumeThreads();
175: VirtualMachine vm = getVM();
176: if (vm != null) {
177: vm.resume();
178: }
179: if (fireNotification) {
180: fireResumeEvent(DebugEvent.CLIENT_REQUEST);
181: }
182: } catch (VMDisconnectedException e) {
183: disconnected();
184: return;
185: } catch (RuntimeException e) {
186: setSuspended(true);
187: fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
188: targetRequestFailed(
189: MessageFormat
190: .format(
191: JDIDebugModelMessages.JDIDebugTarget_exception_resume,
192: new String[] { e.toString() }), e);
193: }
194: }
195:
196: private void setSuspended(boolean suspended) {
197: fSuspended = suspended;
198: }
199:
200: public boolean isSuspended() {
201: return fSuspended;
202: }
203:
204: private void setThreadList(ArrayList threads) {
205: fThreads = threads;
206: }
207:
208: public IThread[] getThreads() {
209: synchronized (fThreads) {
210: return (IThread[]) fThreads.toArray(new IThread[0]);
211: }
212: }
213:
214: protected void removeAllThreads() {
215: Iterator itr = getThreadIterator();
216: while (itr.hasNext()) {
217: DroolsThread child = (DroolsThread) itr.next();
218: child.terminated();
219: }
220: synchronized (fThreads) {
221: fThreads.clear();
222: }
223: }
224:
225: protected void initializeRequests() {
226: setThreadStartHandler(new ThreadStartHandler());
227: new ThreadDeathHandler();
228: new MVELTraceHandler();
229: }
230:
231: class ThreadDeathHandler implements IJDIEventListener {
232:
233: protected ThreadDeathHandler() {
234: createRequest();
235: }
236:
237: /**
238: * Creates and registers a request to listen to thread
239: * death events.
240: */
241: protected void createRequest() {
242: EventRequestManager manager = getEventRequestManager();
243: if (manager != null) {
244: try {
245: EventRequest req = manager
246: .createThreadDeathRequest();
247: req.setSuspendPolicy(EventRequest.SUSPEND_NONE);
248: req.enable();
249: addJDIEventListener(this , req);
250: } catch (RuntimeException e) {
251: logError(e);
252: }
253: }
254: }
255:
256: /**
257: * Locates the model thread associated with the underlying JDI thread
258: * that has terminated, and removes it from the collection of
259: * threads belonging to this debug target. A terminate event is
260: * fired for the model thread.
261: *
262: * @param event a thread death event
263: * @param target the target in which the thread died
264: * @return <code>true</code> - the thread should be resumed
265: */
266: public boolean handleEvent(Event event, JDIDebugTarget target) {
267: ThreadReference ref = ((ThreadDeathEvent) event).thread();
268: DroolsThread thread = (DroolsThread) findThread(ref);
269: if (thread != null) {
270: synchronized (fThreads) {
271: fThreads.remove(thread);
272: }
273: thread.terminated();
274: }
275: return true;
276: }
277:
278: /* (non-Javadoc)
279: * @see org.eclipse.jdt.internal.debug.core.IJDIEventListener#wonSuspendVote(com.sun.jdi.event.Event, org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget)
280: */
281: public void wonSuspendVote(Event event, JDIDebugTarget target) {
282: // do nothing
283: }
284:
285: }
286:
287: class ThreadStartHandler implements IJDIEventListener {
288:
289: protected EventRequest fRequest;
290:
291: protected ThreadStartHandler() {
292: createRequest();
293: }
294:
295: /**
296: * Creates and registers a request to handle all thread start
297: * events
298: */
299: protected void createRequest() {
300: EventRequestManager manager = getEventRequestManager();
301: if (manager != null) {
302: try {
303: EventRequest req = manager
304: .createThreadStartRequest();
305: req.setSuspendPolicy(EventRequest.SUSPEND_NONE);
306: req.enable();
307: addJDIEventListener(this , req);
308: setRequest(req);
309: } catch (RuntimeException e) {
310: logError(e);
311: }
312: }
313: }
314:
315: /**
316: * Creates a model thread for the underlying JDI thread
317: * and adds it to the collection of threads for this
318: * debug target. As a side effect of creating the thread,
319: * a create event is fired for the model thread.
320: * The event is ignored if the underlying thread is already
321: * marked as collected.
322: *
323: * @param event a thread start event
324: * @param target the target in which the thread started
325: * @return <code>true</code> - the thread should be resumed
326: */
327: public boolean handleEvent(Event event, JDIDebugTarget target) {
328: ThreadReference thread = ((ThreadStartEvent) event)
329: .thread();
330: try {
331: if (thread.isCollected()) {
332: return false;
333: }
334: } catch (VMDisconnectedException exception) {
335: return false;
336: } catch (ObjectCollectedException e) {
337: return false;
338: } catch (TimeoutException e) {
339: // continue - attempt to create the thread
340: }
341: DroolsThread jdiThread = (DroolsThread) findThread(thread);
342: if (jdiThread == null) {
343: jdiThread = (DroolsThread) createThread(thread);
344: if (jdiThread == null) {
345: return false;
346: }
347: } else {
348: jdiThread.disposeStackFrames();
349: jdiThread.fireChangeEvent(DebugEvent.CONTENT);
350: }
351: return !jdiThread.isSuspended();
352: }
353:
354: /* (non-Javadoc)
355: * @see org.eclipse.jdt.internal.debug.core.IJDIEventListener#wonSuspendVote(com.sun.jdi.event.Event, org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget)
356: */
357: public void wonSuspendVote(Event event, JDIDebugTarget target) {
358: // do nothing
359: }
360:
361: /**
362: * Deregisters this event listener.
363: */
364: protected void deleteRequest() {
365: if (getRequest() != null) {
366: removeJDIEventListener(this , getRequest());
367: setRequest(null);
368: }
369: }
370:
371: protected EventRequest getRequest() {
372: return fRequest;
373: }
374:
375: protected void setRequest(EventRequest request) {
376: fRequest = request;
377: }
378: }
379:
380: private void disposeThreadHandler() {
381: ThreadStartHandler handler = getThreadStartHandler2();
382: if (handler != null) {
383: handler.deleteRequest();
384: }
385: }
386:
387: public boolean hasThreads() {
388: return fThreads.size() > 0;
389: }
390:
391: protected ThreadStartHandler getThreadStartHandler2() {
392: return fThreadStartHandler;
393: }
394:
395: protected void setThreadStartHandler(
396: ThreadStartHandler threadStartHandler) {
397: fThreadStartHandler = threadStartHandler;
398: }
399:
400: public boolean isOutOfSynch() throws DebugException {
401: Iterator threads = getThreadIterator();
402: while (threads.hasNext()) {
403: JDIThread thread = (JDIThread) threads.next();
404: if (thread.isOutOfSynch()) {
405: return true;
406: }
407: }
408: return false;
409: }
410:
411: public boolean mayBeOutOfSynch() {
412: Iterator threads = getThreadIterator();
413: while (threads.hasNext()) {
414: JDIThread thread = (JDIThread) threads.next();
415: if (thread.mayBeOutOfSynch()) {
416: return true;
417: }
418: }
419: return false;
420: }
421:
422: public JDIThread findThread(ThreadReference tr) {
423: Iterator iter = getThreadIterator();
424: while (iter.hasNext()) {
425: JDIThread thread = (JDIThread) iter.next();
426: if (thread.getUnderlyingThread().equals(tr))
427: return thread;
428: }
429: return null;
430: }
431:
432: public void breakpointRemoved(IBreakpoint breakpoint,
433: IMarkerDelta delta) {
434: if (!isAvailable()) {
435: return;
436: }
437: if (supportsBreakpoint(breakpoint)) {
438: try {
439:
440: if (breakpoint instanceof DroolsLineBreakpoint) {
441: ((DroolsLineBreakpoint) breakpoint)
442: .setJavaBreakpointProperties();
443:
444: final DroolsLineBreakpoint d = (DroolsLineBreakpoint) breakpoint;
445:
446: if (d.getDialectName().equals(MVELDialect.ID)) {
447: removeRemoteBreakpoint(
448: (DroolsLineBreakpoint) breakpoint,
449: delta);
450: }
451: }
452:
453: ((JavaBreakpoint) breakpoint).removeFromTarget(this );
454: getBreakpoints().remove(breakpoint);
455: Iterator threads = getThreadIterator();
456: while (threads.hasNext()) {
457: ((DroolsThread) threads.next())
458: .removeCurrentBreakpoint(breakpoint);
459: }
460: } catch (CoreException e) {
461: logError(e);
462: }
463: }
464: }
465:
466: protected void suspendThreads() {
467: Iterator threads = getThreadIterator();
468: while (threads.hasNext()) {
469: ((DroolsThread) threads.next()).suspendedByVM();
470: }
471: }
472:
473: protected void resumeThreads() throws DebugException {
474: Iterator threads = getThreadIterator();
475: while (threads.hasNext()) {
476: ((DroolsThread) threads.next()).resumedByVM();
477: }
478: }
479:
480: public void disconnect() throws DebugException {
481:
482: if (!isAvailable()) {
483: // already done
484: return;
485: }
486:
487: if (!canDisconnect()) {
488: notSupported(JDIDebugModelMessages.JDIDebugTarget_does_not_support_disconnect);
489: }
490:
491: try {
492: disposeThreadHandler();
493: VirtualMachine vm = getVM();
494: if (vm != null) {
495: vm.dispose();
496: }
497: } catch (VMDisconnectedException e) {
498: // if the VM disconnects while disconnecting, perform
499: // normal disconnect handling
500: disconnected();
501: } catch (RuntimeException e) {
502: targetRequestFailed(
503: MessageFormat
504: .format(
505: JDIDebugModelMessages.JDIDebugTarget_exception_disconnecting,
506: new String[] { e.toString() }), e);
507: }
508:
509: }
510:
511: public void terminate() throws DebugException {
512: if (!isAvailable()) {
513: return;
514: }
515: if (!supportsTerminate()) {
516: notSupported(JDIDebugModelMessages.JDIDebugTarget_does_not_support_termination);
517: }
518: try {
519: setTerminating(true);
520: disposeThreadHandler();
521: VirtualMachine vm = getVM();
522: if (vm != null) {
523: vm.exit(1);
524: }
525: IProcess process = getProcess();
526: if (process != null) {
527: process.terminate();
528: }
529: } catch (VMDisconnectedException e) {
530: // if the VM disconnects while exiting, perform
531: // normal termination processing
532: terminated();
533: } catch (TimeoutException exception) {
534: // if there is a timeout see if the associated process is terminated
535: IProcess process = getProcess();
536: if (process != null && process.isTerminated()) {
537: terminated();
538: } else {
539: // All we can do is disconnect
540: disconnected();
541: }
542: } catch (RuntimeException e) {
543: targetRequestFailed(
544: MessageFormat
545: .format(
546: JDIDebugModelMessages.JDIDebugTarget_exception_terminating,
547: new String[] { e.toString() }), e);
548: }
549: }
550:
551: public void handleVMStart(VMStartEvent event) {
552: if (isResumeOnStartup()) {
553: try {
554: setSuspended(true);
555: resume();
556: } catch (DebugException e) {
557: logError(e);
558: }
559: }
560: // If any threads have resumed since thread collection was initialized,
561: // update their status (avoid concurrent modification - use #getThreads())
562: IThread[] threads = getThreads();
563: for (int i = 0; i < threads.length; i++) {
564: DroolsThread thread = (DroolsThread) threads[i];
565: if (thread.isSuspended()) {
566: try {
567: boolean suspended = thread.getUnderlyingThread()
568: .isSuspended();
569: if (!suspended) {
570: thread.setRunning(true);
571: thread
572: .fireResumeEvent(DebugEvent.CLIENT_REQUEST);
573: }
574: } catch (VMDisconnectedException e) {
575: } catch (ObjectCollectedException e) {
576: } catch (RuntimeException e) {
577: logError(e);
578: }
579: }
580: }
581: }
582:
583: protected void initializeState() {
584:
585: List threads = null;
586: VirtualMachine vm = getVM();
587: if (vm != null) {
588: try {
589: threads = vm.allThreads();
590: } catch (RuntimeException e) {
591: internalError(e);
592: }
593: if (threads != null) {
594: Iterator initialThreads = threads.iterator();
595: while (initialThreads.hasNext()) {
596: createThread((ThreadReference) initialThreads
597: .next());
598: }
599: }
600: }
601:
602: if (isResumeOnStartup()) {
603: setSuspended(false);
604: }
605: }
606:
607: public void suspend() throws DebugException {
608: if (isSuspended()) {
609: return;
610: }
611: try {
612: VirtualMachine vm = getVM();
613: if (vm != null) {
614: vm.suspend();
615: }
616: suspendThreads();
617: setSuspended(true);
618: fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
619: } catch (RuntimeException e) {
620: setSuspended(false);
621: fireResumeEvent(DebugEvent.CLIENT_REQUEST);
622: targetRequestFailed(
623: MessageFormat
624: .format(
625: JDIDebugModelMessages.JDIDebugTarget_exception_suspend,
626: new String[] { e.toString() }), e);
627: }
628: }
629:
630: public void prepareToSuspendByBreakpoint(JavaBreakpoint breakpoint) {
631: setSuspended(true);
632: suspendThreads();
633: }
634:
635: protected void cancelSuspendByBreakpoint(JavaBreakpoint breakpoint)
636: throws DebugException {
637: setSuspended(false);
638: resumeThreads();
639: }
640:
641: class MVELTraceHandler implements IJDIEventListener {
642:
643: protected MVELTraceHandler() {
644: createRequest();
645: }
646:
647: protected void createRequest() {
648: EventRequestManager manager = getEventRequestManager();
649: if (manager != null) {
650: try {
651: ClassPrepareRequest req = manager
652: .createClassPrepareRequest();
653: req
654: .addClassFilter("org.drools.base.mvel.MVELDebugHandler");
655: req.setSuspendPolicy(EventRequest.SUSPEND_ALL);
656: addJDIEventListener(MVELTraceHandler.this , req);
657: req.enable();
658:
659: } catch (RuntimeException e) {
660: logError(e);
661: }
662: }
663: }
664:
665: /**
666: * Locates the model thread associated with the underlying JDI thread
667: * that has terminated, and removes it from the collection of
668: * threads belonging to this debug target. A terminate event is
669: * fired for the model thread.
670: *
671: * @param event a thread death event
672: * @param target the target in which the thread died
673: * @return <code>true</code> - the thread should be resumed
674: */
675: public boolean handleEvent(Event event, JDIDebugTarget target) {
676: String name = ((ClassPrepareEvent) event).referenceType()
677: .name();
678:
679: MethodEntryRequest req = getEventRequestManager()
680: .createMethodEntryRequest();
681: req.addClassFilter(((ClassPrepareEvent) event)
682: .referenceType());
683:
684: //breakpointCatched
685:
686: /*field= type.fieldByName(getFieldName());
687: Field field;
688: EventRequest req= manager.createModificationWatchpointRequest(field);
689: */
690: req.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
691: addJDIEventListener(new IJDIEventListener() {
692:
693: public boolean handleEvent(Event event,
694: JDIDebugTarget target) {
695: MethodEntryEvent entryEvent = (MethodEntryEvent) event;
696:
697: String name2 = entryEvent.method().name();
698:
699: if (!name2.equals("onBreak")
700: && !name2.equals("receiveBreakpoints")) {
701: //event.virtualMachine().resume();
702: return true;
703: }
704:
705: try {
706: IThread[] tharr = getThreads();
707:
708: ThreadReference t = null;
709: DroolsThread t2 = null;
710:
711: for (int i = 0; i < tharr.length; i++) {
712: DroolsThread th2 = (DroolsThread) tharr[i];
713: ThreadReference th2real = ((DroolsThread) tharr[i])
714: .getUnderlyingThread();
715:
716: //MVEL It doesn't have to be always main. find a better way for detection
717: if (th2real.suspendCount() == 1
718: && th2.getName().equals("main")) {
719: t = th2real;
720: t2 = (DroolsThread) th2;
721:
722: th2real.suspend();
723: th2.setRunning(false);
724: th2
725: .fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
726:
727: return true;
728: }
729: }
730: } catch (Exception t) {
731: logError(t);
732: }
733: return true;
734:
735: }
736:
737: public void wonSuspendVote(Event event,
738: JDIDebugTarget target) {
739: // TODO Auto-generated method stub
740:
741: }
742:
743: }, req);
744:
745: req.enable();
746:
747: return true;
748: }
749:
750: /* (non-Javadoc)
751: * @see org.eclipse.jdt.internal.debug.core.IJDIEventListener#wonSuspendVote(com.sun.jdi.event.Event, org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget)
752: */
753: public void wonSuspendVote(Event event, JDIDebugTarget target) {
754: // do nothing
755: }
756:
757: }
758:
759: /**
760: * Tries to find a match for the provided breakpoint information from the list of registered breakpoints.
761: * For stepping and possibly other purposes it returns also a breakpoint for cases where exactly the same line was not found.
762: *
763: * If breakpoint is not found for <code>line</code> at <code>source</code> then it takes the first line that is above the
764: * specified line at the same file.
765: *
766: * @param source
767: * @param line
768: * @return
769: */
770: public DroolsLineBreakpoint getDroolsBreakpoint(String source,
771: int line) {
772:
773: DroolsLineBreakpoint backupBreakpoint = null;
774:
775: Iterator iterator = getBreakpoints().iterator();
776: while (iterator.hasNext()) {
777: IJavaBreakpoint element = (IJavaBreakpoint) iterator.next();
778: if (element instanceof DroolsLineBreakpoint
779: && ((DroolsLineBreakpoint) element)
780: .getDialectName().equals(MVELDialect.ID)) {
781: DroolsLineBreakpoint l = (DroolsLineBreakpoint) element;
782: try {
783:
784: if (l == null || source == null) {
785: return null;
786: }
787:
788: int matchLine = l.getLineNumber();
789: String matchSource = l.getRuleName();
790: if (matchLine == line && source.equals(matchSource)) {
791: return l;
792: }
793:
794: // Prepare for a backup breakpoint
795: if (source.equals(matchSource)
796: || l.getFileRuleMappings().containsKey(
797: source)) {
798: backupBreakpoint = l;
799: }
800:
801: } catch (CoreException e) {
802: logError(e);
803: }
804: }
805: }
806:
807: return backupBreakpoint;
808: }
809:
810: private void addRemoteBreakpoint(DroolsLineBreakpoint d) {
811:
812: try {
813: if (!d.isEnabled()) {
814: return; // No need to install disabled breakpoints
815: }
816: } catch (CoreException e2) {
817: logError(e2);
818: return; // No need to install breakpoints that are this much broken
819: }
820:
821: Iterator handleriter = getVM().classesByName(
822: "org.drools.base.mvel.MVELDebugHandler").iterator();
823: Object debugHandlerClass = handleriter.next();
824:
825: int line;
826: String sourceName;
827:
828: try {
829: line = d.getLineNumber();
830: sourceName = d.getTypeName();
831: } catch (CoreException e1) {
832: logError(e1);
833: return;
834: }
835:
836: ReferenceType refType = (ReferenceType) debugHandlerClass;
837: Method m = (Method) refType.methodsByName("registerBreakpoint")
838: .iterator().next();
839: List args = new ArrayList();
840: IntegerValue lineVal = getVM().mirrorOf(line);
841: StringReference nameVal = getVM().mirrorOf(sourceName);
842: JDIObjectValue val = (JDIObjectValue) newValue(sourceName);
843: ObjectReference realVal = val.getUnderlyingObject();
844: args.add(nameVal);
845: args.add(lineVal);
846:
847: try {
848: ClassType tt = (ClassType) debugHandlerClass;
849: IThread[] tharr = getThreads();
850: ThreadReference t = null;
851: DroolsThread t2 = null;
852:
853: for (int i = 0; i < tharr.length; i++) {
854: IThread th2 = tharr[i];
855: ThreadReference th2real = ((DroolsThread) tharr[i])
856: .getUnderlyingThread();
857: //MVEL It doesn't have to be always main. find a better way for detection. suspend count is most likely only at one thread so a bit more error-safe
858: if (th2real.suspendCount() == 1
859: && th2.getName().equals("main")) {
860: t = th2real;
861: t2 = (DroolsThread) th2;
862: }
863: }
864:
865: tt.invokeMethod(t, m, args,
866: ObjectReference.INVOKE_SINGLE_THREADED);
867: //t2.computeNewStackFrames();
868:
869: super .breakpointAdded(d);
870:
871: } catch (Exception e) {
872: logError(e);
873: }
874:
875: }
876:
877: private void removeRemoteBreakpoint(DroolsLineBreakpoint d,
878: IMarkerDelta delta) {
879: Iterator handleriter = getVM().classesByName(
880: "org.drools.base.mvel.MVELDebugHandler").iterator();
881: Object debugHandlerClass = handleriter.next();
882:
883: int line;
884: String sourceName;
885:
886: try {
887: line = d.getLineNumber();
888: sourceName = d.getTypeName();
889: } catch (CoreException e1) {
890: logError(e1);
891: return;
892: }
893:
894: ReferenceType refType = (ReferenceType) debugHandlerClass;
895: Method m = (Method) refType.methodsByName("removeBreakpoint")
896: .iterator().next();
897: List args = new ArrayList();
898: IntegerValue lineVal = getVM().mirrorOf(line);
899: StringReference nameVal = getVM().mirrorOf(sourceName);
900: JDIObjectValue val = (JDIObjectValue) newValue(sourceName);
901: ObjectReference realVal = val.getUnderlyingObject();
902: args.add(nameVal);
903: args.add(lineVal);
904:
905: try {
906: ClassType tt = (ClassType) debugHandlerClass;
907: IThread[] tharr = getThreads();
908: ThreadReference t = null;
909: DroolsThread t2 = null;
910:
911: for (int i = 0; i < tharr.length; i++) {
912: IThread th2 = tharr[i];
913: ThreadReference th2real = ((DroolsThread) tharr[i])
914: .getUnderlyingThread();
915: //MVEL It doesn't have to be always main. find a better way for detection. suspend count is most likely only at one thread so a bit more error-safe
916: if (th2real.suspendCount() == 1
917: && th2.getName().equals("main")) {
918: t = th2real;
919: t2 = (DroolsThread) th2;
920: }
921: }
922:
923: tt.invokeMethod(t, m, args,
924: ObjectReference.INVOKE_SINGLE_THREADED);
925:
926: } catch (Exception e) {
927: logError(e);
928: }
929:
930: }
931:
932: }
|