KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > core > model > JDIDebugTarget


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.debug.core.model;
12
13
14 import java.io.IOException JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Set JavaDoc;
22
23 import org.eclipse.core.resources.IMarkerDelta;
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.core.runtime.IStatus;
27 import org.eclipse.core.runtime.Status;
28 import org.eclipse.core.runtime.jobs.Job;
29 import org.eclipse.debug.core.DebugEvent;
30 import org.eclipse.debug.core.DebugException;
31 import org.eclipse.debug.core.DebugPlugin;
32 import org.eclipse.debug.core.IBreakpointManager;
33 import org.eclipse.debug.core.IBreakpointManagerListener;
34 import org.eclipse.debug.core.IDebugEventSetListener;
35 import org.eclipse.debug.core.ILaunch;
36 import org.eclipse.debug.core.ILaunchListener;
37 import org.eclipse.debug.core.model.IBreakpoint;
38 import org.eclipse.debug.core.model.IDebugTarget;
39 import org.eclipse.debug.core.model.IMemoryBlock;
40 import org.eclipse.debug.core.model.IProcess;
41 import org.eclipse.debug.core.model.IThread;
42 import org.eclipse.jdi.TimeoutException;
43 import org.eclipse.jdi.internal.VirtualMachineImpl;
44 import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
45 import org.eclipse.jdt.core.IJavaProject;
46 import org.eclipse.jdt.debug.core.IJavaBreakpoint;
47 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
48 import org.eclipse.jdt.debug.core.IJavaThread;
49 import org.eclipse.jdt.debug.core.IJavaThreadGroup;
50 import org.eclipse.jdt.debug.core.IJavaType;
51 import org.eclipse.jdt.debug.core.IJavaValue;
52 import org.eclipse.jdt.debug.core.IJavaVariable;
53 import org.eclipse.jdt.debug.core.JDIDebugModel;
54 import org.eclipse.jdt.debug.eval.EvaluationManager;
55 import org.eclipse.jdt.debug.eval.IAstEvaluationEngine;
56 import org.eclipse.jdt.internal.debug.core.EventDispatcher;
57 import org.eclipse.jdt.internal.debug.core.IJDIEventListener;
58 import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
59 import org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint;
60 import org.eclipse.jdt.internal.debug.core.breakpoints.JavaLineBreakpoint;
61
62 import com.ibm.icu.text.MessageFormat;
63 import com.sun.jdi.ObjectCollectedException;
64 import com.sun.jdi.ReferenceType;
65 import com.sun.jdi.ThreadGroupReference;
66 import com.sun.jdi.ThreadReference;
67 import com.sun.jdi.Type;
68 import com.sun.jdi.VMDisconnectedException;
69 import com.sun.jdi.Value;
70 import com.sun.jdi.VirtualMachine;
71 import com.sun.jdi.event.Event;
72 import com.sun.jdi.event.ThreadDeathEvent;
73 import com.sun.jdi.event.ThreadStartEvent;
74 import com.sun.jdi.event.VMDeathEvent;
75 import com.sun.jdi.event.VMDisconnectEvent;
76 import com.sun.jdi.event.VMStartEvent;
77 import com.sun.jdi.request.ClassPrepareRequest;
78 import com.sun.jdi.request.EventRequest;
79 import com.sun.jdi.request.EventRequestManager;
80
81 /**
82  * Debug target for JDI debug model.
83  */

84
85 public class JDIDebugTarget extends JDIDebugElement implements IJavaDebugTarget, ILaunchListener, IBreakpointManagerListener, IDebugEventSetListener {
86         
87     /**
88      * Threads contained in this debug target. When a thread
89      * starts it is added to the list. When a thread ends it
90      * is removed from the list.
91      */

92     private ArrayList JavaDoc fThreads;
93     
94     /**
95      * List of thread groups in this target.
96      */

97     private ArrayList JavaDoc fGroups;
98     
99     /**
100      * Associated system process, or <code>null</code> if not available.
101      */

102     private IProcess fProcess;
103     /**
104      * Underlying virtual machine.
105      */

106     private VirtualMachine fVirtualMachine;
107     /**
108      * Whether terminate is supported. Not all targets
109      * support terminate. For example, a VM that was attached
110      * to remotely may not allow the user to terminate it.
111      */

112     private boolean fSupportsTerminate;
113     /**
114      * Whether terminated
115      */

116     private boolean fTerminated;
117     
118     /**
119      * Whether in the process of terminating
120      */

121     private boolean fTerminating;
122     /**
123      * Whether disconnected
124      */

125     private boolean fDisconnected;
126     /**
127      * Whether disconnect is supported.
128      */

129     private boolean fSupportsDisconnect;
130     /**
131      * Collection of breakpoints added to this target. Values are of type <code>IJavaBreakpoint</code>.
132      */

133     private List JavaDoc fBreakpoints;
134     
135     /**
136      * Collection of types that have attempted HCR, but failed.
137      * The types are stored by their fully qualified names.
138      */

139     private Set JavaDoc fOutOfSynchTypes;
140     /**
141      * Whether or not this target has performed a hot code replace.
142      */

143     private boolean fHasHCROccurred;
144     
145     /**
146      * The name of this target - set by the client on creation, or retrieved from the
147      * underlying VM.
148      */

149     private String JavaDoc fName;
150
151     /**
152      * The event dispatcher for this debug target, which runs in its
153      * own thread.
154      */

155     private EventDispatcher fEventDispatcher= null;
156     
157     /**
158      * The thread start event handler
159      */

160     private ThreadStartHandler fThreadStartHandler= null;
161     
162     /**
163      * Whether this VM is suspended.
164      */

165     private boolean fSuspended = true;
166     
167     /**
168      * Whether the VM should be resumed on startup
169      */

170     private boolean fResumeOnStartup = false;
171     
172     /**
173      * The launch this target is contained in
174      */

175     private ILaunch fLaunch;
176     
177     /**
178      * Count of the number of suspend events in this target
179      */

180     private int fSuspendCount = 0;
181     
182     /**
183      * Evaluation engine cache by Java project. Engines
184      * are disposed when this target terminates.
185      */

186     private HashMap JavaDoc fEngines;
187     
188     /**
189      * List of step filters - each string is a pattern/fully qualified
190      * name of a type to filter.
191      */

192     private String JavaDoc[] fStepFilters = null;
193     
194     /**
195      * Step filter state mask.
196      */

197     private int fStepFilterMask = 0;
198     
199     /**
200      * Step filter bit mask - indicates if step filters are enabled.
201      */

202     private static final int STEP_FILTERS_ENABLED = 0x001;
203     
204     /**
205      * Step filter bit mask - indicates if synthetic methods are filtered.
206      */

207     private static final int FILTER_SYNTHETICS = 0x002;
208     
209     /**
210      * Step filter bit mask - indicates if static initializers are filtered.
211      */

212     private static final int FILTER_STATIC_INITIALIZERS = 0x004;
213     
214     /**
215      * Step filter bit mask - indicates if constructors are filtered.
216      */

217     private static final int FILTER_CONSTRUCTORS = 0x008;
218     
219     /**
220      * When a step lands in a filtered location, this indicates whether stepping
221      * should proceed "through" to an un-filtered location or step return.
222      * @since 3.3
223      */

224     private static final int STEP_THRU_FILTERS = 0x010;
225     
226     /**
227      * Mask used to flip individual bit masks via XOR
228      */

229     private static final int XOR_MASK = 0xFFF;
230     /**
231      * Whether this debug target is currently performing a hot code replace
232      */

233     private boolean fIsPerformingHotCodeReplace= false;
234     
235      
236     /**
237      * Creates a new JDI debug target for the given virtual machine.
238      *
239      * @param jvm the underlying VM
240      * @param name the name to use for this VM, or <code>null</code>
241      * if the name should be retrieved from the underlying VM
242      * @param supportsTerminate whether the terminate action
243      * is supported by this debug target
244      * @param supportsDisconnect whether the disconnect action is
245      * supported by this debug target
246      * @param process the system process associated with the
247      * underlying VM, or <code>null</code> if no system process
248      * is available (for example, a remote VM)
249      * @param resume whether the VM should be resumed on startup.
250      * Has no effect if the VM is already resumed/running when
251      * the connection is made.
252      */

253     public JDIDebugTarget(ILaunch launch, VirtualMachine jvm, String JavaDoc name, boolean supportTerminate, boolean supportDisconnect, IProcess process, boolean resume) {
254         super(null);
255         setLaunch(launch);
256         setResumeOnStartup(resume);
257         setSupportsTerminate(supportTerminate);
258         setSupportsDisconnect(supportDisconnect);
259         setVM(jvm);
260         jvm.setDebugTraceMode(VirtualMachine.TRACE_NONE);
261         setProcess(process);
262         setTerminated(false);
263         setTerminating(false);
264         setDisconnected(false);
265         setName(name);
266         setBreakpoints(new ArrayList JavaDoc(5));
267         setThreadList(new ArrayList JavaDoc(5));
268         fGroups = new ArrayList JavaDoc(5);
269         setOutOfSynchTypes(new ArrayList JavaDoc(0));
270         setHCROccurred(false);
271         initialize();
272         DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
273         DebugPlugin.getDefault().getBreakpointManager().addBreakpointManagerListener(this);
274     }
275
276     /**
277      * Returns the event dispatcher for this debug target.
278      * There is one event dispatcher per debug target.
279      *
280      * @return event dispatcher
281      */

282     public EventDispatcher getEventDispatcher() {
283         return fEventDispatcher;
284     }
285     
286     /**
287      * Sets the event dispatcher for this debug target.
288      * Set once at initialization.
289      *
290      * @param dispatcher event dispatcher
291      * @see #initialize()
292      */

293     private void setEventDispatcher(EventDispatcher dispatcher) {
294         fEventDispatcher = dispatcher;
295     }
296     
297     /**
298      * Returns an iterator over the collection of threads. The
299      * returned iterator is made on a copy of the thread list
300      * so that it is thread safe. This method should always be
301      * used instead of getThreadList().iterator()
302      * @return an iterator over the collection of threads
303      */

304     private Iterator JavaDoc getThreadIterator() {
305         List JavaDoc threadList;
306         synchronized (fThreads) {
307             threadList= (List JavaDoc) fThreads.clone();
308         }
309         return threadList.iterator();
310     }
311     
312     /**
313      * Sets the list of threads contained in this debug target.
314      * Set to an empty collection on creation. Threads are
315      * added and removed as they start and end. On termination
316      * this collection is set to the immutable singleton empty list.
317      *
318      * @param threads empty list
319      */

320     private void setThreadList(ArrayList JavaDoc threads) {
321         fThreads = threads;
322     }
323     
324     /**
325      * Returns the collection of breakpoints installed in this
326      * debug target.
327      *
328      * @return list of installed breakpoints - instances of
329      * <code>IJavaBreakpoint</code>
330      */

331     public List JavaDoc getBreakpoints() {
332         return fBreakpoints;
333     }
334     
335     /**
336      * Sets the list of breakpoints installed in this debug
337      * target. Set to an empty list on creation.
338      *
339      * @param breakpoints empty list
340      */

341     private void setBreakpoints(List JavaDoc breakpoints) {
342         fBreakpoints = breakpoints;
343     }
344         
345     /**
346      * Notifies this target that the underlying VM has started.
347      * This is the first event received from the VM.
348      * The VM is resumed. This event is not generated when
349      * an attach is made to a VM that is already running
350      * (has already started up). The VM is resumed as specified
351      * on creation.
352      *
353      * @param event VM start event
354      */

355     public void handleVMStart(VMStartEvent event) {
356         if (isResumeOnStartup()) {
357             try {
358                 setSuspended(true);
359                 resume();
360             } catch (DebugException e) {
361                 logError(e);
362             }
363         }
364         // If any threads have resumed since thread collection was initialized,
365
// update their status (avoid concurrent modification - use #getThreads())
366
IThread[] threads = getThreads();
367         for (int i = 0; i < threads.length; i++) {
368             JDIThread thread = (JDIThread)threads[i];
369             if (thread.isSuspended()) {
370                 try {
371                     boolean suspended = thread.getUnderlyingThread().isSuspended();
372                     if (!suspended) {
373                         thread.setRunning(true);
374                         thread.fireResumeEvent(DebugEvent.CLIENT_REQUEST);
375                     }
376                 } catch (VMDisconnectedException e) {
377                 } catch (ObjectCollectedException e){
378                 } catch (RuntimeException JavaDoc e) {
379                     logError(e);
380                 }
381             }
382         }
383         
384     }
385      
386     /**
387      * Initialize event requests and state from the underlying VM.
388      * This method is synchronized to ensure that we do not start
389      * to process an events from the target until our state is
390      * initialized.
391      */

392     protected synchronized void initialize() {
393         setEventDispatcher(new EventDispatcher(this));
394         setRequestTimeout(JDIDebugModel.getPreferences().getInt(JDIDebugModel.PREF_REQUEST_TIMEOUT));
395         initializeRequests();
396         initializeState();
397         initializeBreakpoints();
398         getLaunch().addDebugTarget(this);
399         DebugPlugin plugin = DebugPlugin.getDefault();
400         plugin.addDebugEventListener(this);
401         fireCreationEvent();
402         // begin handling/dispatching events after the creation event is handled by all listeners
403
plugin.asyncExec(new Runnable JavaDoc() {
404             public void run() {
405                 EventDispatcher dispatcher = getEventDispatcher();
406                 if (dispatcher != null) {
407                     Thread JavaDoc t= new Thread JavaDoc(dispatcher, JDIDebugModel.getPluginIdentifier() + JDIDebugModelMessages.JDIDebugTarget_JDI_Event_Dispatcher);
408                     t.setDaemon(true);
409                     t.start();
410                 }
411             }
412         });
413     }
414     
415     /**
416      * Adds all of the pre-existing threads to this debug target.
417      */

418     protected void initializeState() {
419
420         List JavaDoc threads= null;
421         VirtualMachine vm = getVM();
422         if (vm != null) {
423             try {
424                 threads= vm.allThreads();
425             } catch (RuntimeException JavaDoc e) {
426                 internalError(e);
427             }
428             if (threads != null) {
429                 Iterator JavaDoc initialThreads= threads.iterator();
430                 while (initialThreads.hasNext()) {
431                     createThread((ThreadReference) initialThreads.next());
432                 }
433             }
434         }
435         
436         if (isResumeOnStartup()) {
437             setSuspended(false);
438         }
439     }
440      
441     /**
442      * Registers event handlers for thread creation,
443      * thread termination.
444      */

445     protected void initializeRequests() {
446         setThreadStartHandler(new ThreadStartHandler());
447         new ThreadDeathHandler();
448     }
449
450     /**
451      * Installs all Java breakpoints that currently exist in
452      * the breakpoint manager
453      */

454     protected void initializeBreakpoints() {
455         IBreakpointManager manager= DebugPlugin.getDefault().getBreakpointManager();
456         manager.addBreakpointListener(this);
457         IBreakpoint[] bps = manager.getBreakpoints(JDIDebugModel.getPluginIdentifier());
458         for (int i = 0; i < bps.length; i++) {
459             if (bps[i] instanceof IJavaBreakpoint) {
460                 breakpointAdded(bps[i]);
461             }
462         }
463     }
464         
465     /**
466      * Creates, adds and returns a thread for the given
467      * underlying thread reference. A creation event
468      * is fired for the thread.
469      * Returns <code>null</code> if during the creation of the thread this target
470      * is set to the disconnected state.
471      *
472      * @param thread underlying thread
473      * @return model thread
474      */

475     protected JDIThread createThread(ThreadReference thread) {
476         JDIThread jdiThread= newThread(thread);
477         if (jdiThread == null) {
478             return null;
479         }
480         if (isDisconnected()) {
481             return null;
482         }
483         synchronized (fThreads) {
484             fThreads.add(jdiThread);
485         }
486         jdiThread.fireCreationEvent();
487         return jdiThread;
488     }
489     
490     /**
491      * Factory method for creating new threads. Creates and returns a new thread
492      * object for the underlying thread reference, or <code>null</code> if none
493      *
494      * @param reference thread reference
495      * @return JDI model thread
496      */

497     protected JDIThread newThread(ThreadReference reference) {
498         try {
499             return new JDIThread(this, reference);
500         } catch (ObjectCollectedException exception) {
501             // ObjectCollectionException can be thrown if the thread has already
502
// completed (exited) in the VM.
503
}
504         return null;
505     }
506     
507     /**
508      * @see IDebugTarget#getThreads()
509      */

510     public IThread[] getThreads() {
511         synchronized (fThreads) {
512             return (IThread[])fThreads.toArray(new IThread[0]);
513         }
514     }
515     
516     /**
517      * @see ISuspendResume#canResume()
518      */

519     public boolean canResume() {
520         return (isSuspended() || hasSuspendedThreads())
521             && isAvailable() && !isPerformingHotCodeReplace();
522     }
523
524     /**
525      * Returns whether this target has any threads which are suspended.
526      * @return true if any thread is suspended, false otherwise
527      * @since 3.2
528      */

529     private boolean hasSuspendedThreads() {
530         Iterator JavaDoc it = getThreadIterator();
531         while(it.hasNext()){
532             IThread thread = (IThread)it.next();
533             if(thread.isSuspended())
534                 return true;
535         }
536         return false;
537     }
538
539     /**
540      * @see ISuspendResume#canSuspend()
541      */

542     public boolean canSuspend() {
543         if (!isSuspended() && isAvailable()) {
544             // only allow suspend if no threads are currently suspended
545
IThread[] threads= getThreads();
546             for (int i= 0, numThreads= threads.length; i < numThreads; i++) {
547                 if (((JDIThread)threads[i]).isSuspended()) {
548                     return false;
549                 }
550             }
551             return true;
552         }
553         return false;
554     }
555
556     /**
557      * @see ITerminate#canTerminate()
558      */

559     public boolean canTerminate() {
560         return supportsTerminate() && isAvailable();
561     }
562
563     /**
564      * @see IDisconnect#canDisconnect()
565      */

566     public boolean canDisconnect() {
567         return supportsDisconnect() && !isDisconnected();
568     }
569     
570     /**
571      * Returns whether this debug target supports disconnecting.
572      *
573      * @return whether this debug target supports disconnecting
574      */

575     protected boolean supportsDisconnect() {
576         return fSupportsDisconnect;
577     }
578     
579     /**
580      * Sets whether this debug target supports disconnection.
581      * Set on creation.
582      *
583      * @param supported <code>true</code> if this target supports
584      * disconnection, otherwise <code>false</code>
585      */

586     private void setSupportsDisconnect(boolean supported) {
587         fSupportsDisconnect = supported;
588     }
589     
590     /**
591      * Returns whether this debug target supports termination.
592      *
593      * @return whether this debug target supports termination
594      */

595     protected boolean supportsTerminate() {
596         return fSupportsTerminate;
597     }
598     
599     /**
600      * Sets whether this debug target supports termination.
601      * Set on creation.
602      *
603      * @param supported <code>true</code> if this target supports
604      * termination, otherwise <code>false</code>
605      */

606     private void setSupportsTerminate(boolean supported) {
607         fSupportsTerminate = supported;
608     }
609     
610     /**
611      * @see IJavaDebugTarget#supportsHotCodeReplace()
612      */

613     public boolean supportsHotCodeReplace() {
614         return supportsJ9HotCodeReplace() || supportsJDKHotCodeReplace();
615     }
616     
617     /**
618      * @see IJavaDebugTarget#supportsInstanceBreakpoints()
619      */

620     public boolean supportsInstanceBreakpoints() {
621         if (isAvailable() && JDIDebugPlugin.isJdiVersionGreaterThanOrEqual(new int[] {1,4})) {
622             VirtualMachine vm = getVM();
623             if (vm != null) {
624                 return vm.canUseInstanceFilters();
625             }
626         }
627         return false;
628     }
629     
630     /**
631      * Returns whether this debug target supports hot code replace for the J9 VM.
632      *
633      * @return whether this debug target supports J9 hot code replace
634      */

635     public boolean supportsJ9HotCodeReplace() {
636         VirtualMachine vm = getVM();
637         if (isAvailable() && vm instanceof org.eclipse.jdi.hcr.VirtualMachine) {
638             try {
639                 return ((org.eclipse.jdi.hcr.VirtualMachine)vm).canReloadClasses();
640             } catch (UnsupportedOperationException JavaDoc e) {
641                 // This is not an error condition - UnsupportedOperationException is thrown when a VM does
642
// not support HCR
643
}
644         }
645         return false;
646     }
647     
648     /**
649      * Returns whether this debug target supports hot code replace for JDK VMs.
650      *
651      * @return whether this debug target supports JDK hot code replace
652      */

653     public boolean supportsJDKHotCodeReplace() {
654         if (isAvailable() && JDIDebugPlugin.isJdiVersionGreaterThanOrEqual(new int[] {1,4})) {
655             VirtualMachine vm = getVM();
656             if (vm != null) {
657                 return vm.canRedefineClasses();
658             }
659         }
660         return false;
661     }
662     
663     /**
664      * Returns whether this debug target supports popping stack frames.
665      *
666      * @return whether this debug target supports popping stack frames.
667      */

668     public boolean canPopFrames() {
669         if (isAvailable() && JDIDebugPlugin.isJdiVersionGreaterThanOrEqual(new int[] {1,4})) {
670             VirtualMachine vm = getVM();
671             if (vm != null) {
672                 return vm.canPopFrames();
673             }
674         }
675         return false;
676     }
677
678     /**
679      * @see IDisconnect#disconnect()
680      */

681     public void disconnect() throws DebugException {
682
683         if (!isAvailable()) {
684             // already done
685
return;
686         }
687
688         if (!canDisconnect()) {
689             notSupported(JDIDebugModelMessages.JDIDebugTarget_does_not_support_disconnect);
690         }
691
692         try {
693             disposeThreadHandler();
694             VirtualMachine vm = getVM();
695             if (vm != null) {
696                 vm.dispose();
697             }
698         } catch (VMDisconnectedException e) {
699             // if the VM disconnects while disconnecting, perform
700
// normal disconnect handling
701
disconnected();
702         } catch (RuntimeException JavaDoc e) {
703             targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIDebugTarget_exception_disconnecting, new String JavaDoc[] {e.toString()}), e);
704         }
705
706     }
707     
708     /**
709      * Allows for ThreadStartHandler to do clean up/disposal.
710      */

711     private void disposeThreadHandler() {
712         ThreadStartHandler handler = getThreadStartHandler();
713         if (handler != null) {
714             handler.deleteRequest();
715         }
716     }
717
718     /**
719      * Returns the underlying virtual machine associated with this
720      * debug target, or <code>null</code> if none (disconnected/terminated)
721      *
722      * @return the underlying VM or <code>null</code>
723      */

724     public VirtualMachine getVM() {
725         return fVirtualMachine;
726     }
727     
728     /**
729      * Sets the underlying VM associated with this debug
730      * target. Set on creation.
731      *
732      * @param vm underlying VM
733      */

734     private void setVM(VirtualMachine vm) {
735         fVirtualMachine = vm;
736     }
737     
738     /**
739      * Sets whether this debug target has performed a hot
740      * code replace.
741      */

742     public void setHCROccurred(boolean occurred) {
743         fHasHCROccurred= occurred;
744     }
745     
746     public void removeOutOfSynchTypes(List JavaDoc qualifiedNames) {
747         fOutOfSynchTypes.removeAll(qualifiedNames);
748     }
749     
750     /**
751      * Sets the list of out of synch types
752      * to the given list.
753      */

754     private void setOutOfSynchTypes(List JavaDoc qualifiedNames) {
755         fOutOfSynchTypes= new HashSet JavaDoc();
756         fOutOfSynchTypes.addAll(qualifiedNames);
757     }
758     
759     /**
760      * The given types have failed to be reloaded by HCR.
761      * Add them to the list of out of synch types.
762      */

763     public void addOutOfSynchTypes(List JavaDoc qualifiedNames) {
764         fOutOfSynchTypes.addAll(qualifiedNames);
765     }
766     
767     /**
768      * Returns whether the given type is out of synch in this
769      * target.
770      */

771     public boolean isOutOfSynch(String JavaDoc qualifiedName) {
772         if (fOutOfSynchTypes == null || fOutOfSynchTypes.isEmpty()) {
773             return false;
774         }
775         return fOutOfSynchTypes.contains(qualifiedName);
776     }
777     
778     /**
779      * @see IJavaDebugTarget#isOutOfSynch()
780      */

781     public boolean isOutOfSynch() throws DebugException {
782         Iterator JavaDoc threads= getThreadIterator();
783         while (threads.hasNext()) {
784             JDIThread thread= (JDIThread)threads.next();
785             if (thread.isOutOfSynch()) {
786                 return true;
787             }
788         }
789         return false;
790     }
791     
792     /**
793      * @see IJavaDebugTarget#mayBeOutOfSynch()
794      */

795     public boolean mayBeOutOfSynch() {
796         Iterator JavaDoc threads= getThreadIterator();
797         while (threads.hasNext()) {
798             JDIThread thread= (JDIThread)threads.next();
799             if (thread.mayBeOutOfSynch()) {
800                 return true;
801             }
802         }
803         return false;
804     }
805     
806     /**
807      * Returns whether a hot code replace attempt has failed.
808      *
809      * HCR has failed if there are any out of synch types
810      */

811     public boolean hasHCRFailed() {
812         return fOutOfSynchTypes != null && !fOutOfSynchTypes.isEmpty();
813     }
814     
815     /**
816      * Returns whether this debug target has performed
817      * a hot code replace
818      */

819     public boolean hasHCROccurred() {
820         return fHasHCROccurred;
821     }
822     
823     /**
824      * Reinstall all breakpoints installed in the given resources
825      */

826     public void reinstallBreakpointsIn(List JavaDoc resources, List JavaDoc classNames) {
827         List JavaDoc breakpoints= getBreakpoints();
828         IJavaBreakpoint[] copy= new IJavaBreakpoint[breakpoints.size()];
829         breakpoints.toArray(copy);
830         IJavaBreakpoint breakpoint= null;
831         String JavaDoc installedType= null;
832         
833         for (int i= 0; i < copy.length; i++) {
834             breakpoint= copy[i];
835             if (breakpoint instanceof JavaLineBreakpoint) {
836                 try {
837                     installedType= breakpoint.getTypeName();
838                     if (classNames.contains(installedType)) {
839                         breakpointRemoved(breakpoint, null);
840                         breakpointAdded(breakpoint);
841                     }
842                 } catch (CoreException ce) {
843                     logError(ce);
844                     continue;
845                 }
846             }
847         }
848     }
849
850     /**
851      * Finds and returns the JDI thread for the associated thread reference,
852      * or <code>null</code> if not found.
853      *
854      * @param the underlying thread reference
855      * @return the associated model thread
856      */

857     public JDIThread findThread(ThreadReference tr) {
858         Iterator JavaDoc iter= getThreadIterator();
859         while (iter.hasNext()) {
860             JDIThread thread = (JDIThread) iter.next();
861             if (thread.getUnderlyingThread().equals(tr))
862                 return thread;
863         }
864         return null;
865     }
866
867     /**
868      * @see IDebugElement#getName()
869      */

870     public String JavaDoc getName() throws DebugException {
871         if (fName == null) {
872             VirtualMachine vm = getVM();
873             if (vm == null) {
874                 requestFailed(JDIDebugModelMessages.JDIDebugTarget_Unable_to_retrieve_name___VM_disconnected__1, null);
875             }
876             try {
877                 setName(vm.name());
878             } catch (RuntimeException JavaDoc e) {
879                 targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIDebugTarget_exception_retrieving_name, new String JavaDoc[] {e.toString()}), e);
880                 // execution will not reach this line, as
881
// #targetRequestFailed will throw an exception
882
return null;
883             }
884         }
885         return fName;
886     }
887     
888     /**
889      * Sets the name of this debug target. Set on creation,
890      * and if set to <code>null</code> the name will be
891      * retrieved lazily from the underlying VM.
892      *
893      * @param name the name of this VM or <code>null</code>
894      * if the name should be retrieved from the underlying VM
895      */

896     protected void setName(String JavaDoc name) {
897         fName = name;
898     }
899     
900     /**
901      * Sets the process associated with this debug target,
902      * possibly <code>null</code>. Set on creation.
903      *
904      * @param process the system process associated with the
905      * underlying VM, or <code>null</code> if no process is
906      * associated with this debug target (for example, a remote
907      * VM).
908      */

909     protected void setProcess(IProcess process) {
910         fProcess = process;
911     }
912     
913     /**
914      * @see IDebugTarget#getProcess()
915      */

916     public IProcess getProcess() {
917         return fProcess;
918     }
919     
920     /**
921      * Notification the underlying VM has died. Updates
922      * the state of this target to be terminated.
923      *
924      * @param event VM death event
925      */

926     public void handleVMDeath(VMDeathEvent event) {
927         terminated();
928     }
929
930     /**
931      * Notification the underlying VM has disconnected.
932      * Updates the state of this target to be terminated.
933      *
934      * @param event disconnect event
935      */

936     public void handleVMDisconnect(VMDisconnectEvent event) {
937         if (isTerminating()) {
938             terminated();
939         } else {
940             disconnected();
941         }
942     }
943     
944     /**
945      * @see ISuspendResume#isSuspended()
946      */

947     public boolean isSuspended() {
948         return fSuspended;
949     }
950     
951     /**
952      * Sets whether this VM is suspended.
953      *
954      * @param suspended whether this VM is suspended
955      */

956     private void setSuspended(boolean suspended) {
957         fSuspended = suspended;
958     }
959     
960     /**
961      * Returns whether this target is available to
962      * handle VM requests
963      */

964     public boolean isAvailable() {
965         return !(isTerminated() || isTerminating() || isDisconnected());
966     }
967
968     /**
969      * @see ITerminate#isTerminated()
970      */

971     public boolean isTerminated() {
972         return fTerminated;
973     }
974
975     /**
976      * Sets whether this debug target is terminated
977      *
978      * @param terminated <code>true</code> if this debug
979      * target is terminated, otherwise <code>false</code>
980      */

981     protected void setTerminated(boolean terminated) {
982         fTerminated = terminated;
983     }
984     
985     /**
986      * Sets whether this debug target is disconnected
987      *
988      * @param disconnected <code>true</code> if this debug
989      * target is disconnected, otherwise <code>false</code>
990      */

991     protected void setDisconnected(boolean disconnected) {
992         fDisconnected= disconnected;
993     }
994     
995     /**
996      * @see IDisconnect#isDisconnected()
997      */

998     public boolean isDisconnected() {
999         return fDisconnected;
1000    }
1001    
1002    /**
1003     * Creates, enables and returns a class prepare request for the
1004     * specified class name in this target.
1005     *
1006     * @param classPattern regular expression specifying the pattern of
1007     * class names that will cause the event request to fire. Regular
1008     * expressions may begin with a '*', end with a '*', or be an exact
1009     * match.
1010     * @exception CoreException if unable to create the request
1011     */

1012    public ClassPrepareRequest createClassPrepareRequest(String JavaDoc classPattern) throws CoreException {
1013        return createClassPrepareRequest(classPattern, null);
1014    }
1015    
1016    /**
1017     * Creates, enables and returns a class prepare request for the
1018     * specified class name in this target. Can specify a class exclusion filter
1019     * as well.
1020     * This is a utility method used by event requesters that need to
1021     * create class prepare requests.
1022     *
1023     * @param classPattern regular expression specifying the pattern of
1024     * class names that will cause the event request to fire. Regular
1025     * expressions may begin with a '*', end with a '*', or be an exact
1026     * match.
1027     * @param classExclusionPattern regular expression specifying the pattern of
1028     * class names that will not cause the event request to fire. Regular
1029     * expressions may begin with a '*', end with a '*', or be an exact
1030     * match. May be <code>null</code>.
1031     * @exception CoreException if unable to create the request
1032     */

1033    public ClassPrepareRequest createClassPrepareRequest(String JavaDoc classPattern, String JavaDoc classExclusionPattern) throws CoreException {
1034        return createClassPrepareRequest(classPattern, classExclusionPattern, true);
1035    }
1036    
1037    /**
1038     * Creates, enables and returns a class prepare request for the
1039     * specified class name in this target. Can specify a class exclusion filter
1040     * as well.
1041     * This is a utility method used by event requesters that need to
1042     * create class prepare requests.
1043     *
1044     * @param classPattern regular expression specifying the pattern of
1045     * class names that will cause the event request to fire. Regular
1046     * expressions may begin with a '*', end with a '*', or be an exact
1047     * match.
1048     * @param classExclusionPattern regular expression specifying the pattern of
1049     * class names that will not cause the event request to fire. Regular
1050     * expressions may begin with a '*', end with a '*', or be an exact
1051     * match. May be <code>null</code>.
1052     * @param enabled whether to enable the event request
1053     * @exception CoreException if unable to create the request
1054     * @since 3.3
1055     */

1056    public ClassPrepareRequest createClassPrepareRequest(String JavaDoc classPattern, String JavaDoc classExclusionPattern, boolean enabled) throws CoreException {
1057        return createClassPrepareRequest(classPattern, classExclusionPattern, enabled, null);
1058    }
1059    
1060    /**
1061     * Creates, enables and returns a class prepare request for the
1062     * specified class name in this target. Can specify a class exclusion filter
1063     * as well.
1064     * This is a utility method used by event requesters that need to
1065     * create class prepare requests.
1066     *
1067     * @param classPattern regular expression specifying the pattern of
1068     * class names that will cause the event request to fire. Regular
1069     * expressions may begin with a '*', end with a '*', or be an exact
1070     * match. May be <code>null</code> if sourceName is specified
1071     * @param classExclusionPattern regular expression specifying the pattern of
1072     * class names that will not cause the event request to fire. Regular
1073     * expressions may begin with a '*', end with a '*', or be an exact
1074     * match. May be <code>null</code>.
1075     * @param enabled whether to enable the event request
1076     * @param sourceName source name pattern to match or <code>null</code> if classPattern
1077     * is specified
1078     * @exception CoreException if unable to create the request
1079     * @since 3.3
1080     */

1081    public ClassPrepareRequest createClassPrepareRequest(String JavaDoc classPattern, String JavaDoc classExclusionPattern, boolean enabled, String JavaDoc sourceName) throws CoreException {
1082        EventRequestManager manager= getEventRequestManager();
1083        if (!isAvailable() || manager == null) {
1084            requestFailed(JDIDebugModelMessages.JDIDebugTarget_Unable_to_create_class_prepare_request___VM_disconnected__2, null);
1085        }
1086        ClassPrepareRequest req= null;
1087        try {
1088            req= manager.createClassPrepareRequest();
1089            if (classPattern != null) {
1090                req.addClassFilter(classPattern);
1091            }
1092            if (classExclusionPattern != null) {
1093                req.addClassExclusionFilter(classExclusionPattern);
1094            }
1095            req.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
1096            if (sourceName != null) {
1097                req.addSourceNameFilter(sourceName);
1098            }
1099            if (enabled) {
1100                req.enable();
1101            }
1102        } catch (RuntimeException JavaDoc e) {
1103            targetRequestFailed(JDIDebugModelMessages.JDIDebugTarget_Unable_to_create_class_prepare_request__3, e);
1104            // execution will not reach here
1105
return null;
1106        }
1107        return req;
1108    }
1109
1110    /**
1111     * @see ISuspendResume#resume()
1112     */

1113    public void resume() throws DebugException {
1114        // if a client calls resume, then we should resume on a VMStart event in case
1115
// it has not yet been received, and the target was created with the "resume"
1116
// flag as "false". See bug 32372.
1117
setResumeOnStartup(true);
1118        resume(true);
1119    }
1120    
1121    /**
1122     * @see ISuspendResume#resume()
1123     *
1124     * Updates the state of this debug target to resumed,
1125     * but does not fire notification of the resumption.
1126     */

1127    public void resumeQuiet() throws DebugException {
1128        resume(false);
1129    }
1130    
1131    /**
1132     * @see ISuspendResume#resume()
1133     *
1134     * Updates the state of this debug target, but only fires
1135     * notification to listeners if <code>fireNotification</code>
1136     * is <code>true</code>.
1137     */

1138    protected void resume(boolean fireNotification) throws DebugException {
1139        if ((!isSuspended() && !hasSuspendedThreads())
1140            || !isAvailable()) {
1141            return;
1142        }
1143        try {
1144            setSuspended(false);
1145            resumeThreads();
1146            VirtualMachine vm = getVM();
1147            if (vm != null) {
1148                vm.resume();
1149            }
1150            if (fireNotification) {
1151                fireResumeEvent(DebugEvent.CLIENT_REQUEST);
1152            }
1153        } catch (VMDisconnectedException e) {
1154            disconnected();
1155            return;
1156        } catch (RuntimeException JavaDoc e) {
1157            setSuspended(true);
1158            fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
1159            targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIDebugTarget_exception_resume, new String JavaDoc[] {e.toString()}), e);
1160        }
1161    }
1162    
1163    /**
1164     * @see org.eclipse.debug.core.model.IDebugTarget#supportsBreakpoint(IBreakpoint)
1165     */

1166    public boolean supportsBreakpoint(IBreakpoint breakpoint) {
1167        return breakpoint instanceof IJavaBreakpoint;
1168    }
1169
1170    /**
1171     * Notification a breakpoint has been added to the
1172     * breakpoint manager. If the breakpoint is a Java
1173     * breakpoint and this target is not terminated,
1174     * the breakpoint is installed.
1175     *
1176     * @param breakpoint the breakpoint added to
1177     * the breakpoint manager
1178     */

1179    public void breakpointAdded(IBreakpoint breakpoint) {
1180        if (!isAvailable()) {
1181            return;
1182        }
1183        if (supportsBreakpoint(breakpoint)) {
1184            try {
1185                JavaBreakpoint javaBreakpoint= (JavaBreakpoint) breakpoint;
1186                if (!getBreakpoints().contains(breakpoint)) {
1187                    if (!javaBreakpoint.shouldSkipBreakpoint()) {
1188                        // If the breakpoint should be skipped, don't add the breakpoint
1189
// request to the VM. Just add the breakpoint to the collection so
1190
// we have it if the manager is later enabled.
1191
javaBreakpoint.addToTarget(this);
1192                    }
1193                    getBreakpoints().add(breakpoint);
1194                }
1195            } catch (CoreException e) {
1196                logError(e);
1197            }
1198        }
1199    }
1200
1201    /**
1202     * Notification that one or more attributes of the
1203     * given breakpoint has changed. If the breakpoint
1204     * is a Java breakpoint, the associated event request
1205     * in the underlying VM is updated to reflect the
1206     * new state of the breakpoint.
1207     *
1208     * @param breakpoint the breakpoint that has changed
1209     */

1210    public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
1211    }
1212    
1213    /**
1214     * Notification that the given breakpoint has been removed
1215     * from the breakpoint manager. If this target is not terminated,
1216     * the breakpoint is removed from the underlying VM.
1217     *
1218     * @param breakpoint the breakpoint has been removed from
1219     * the breakpoint manager.
1220     */

1221    public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
1222        if (!isAvailable()) {
1223            return;
1224        }
1225        if (supportsBreakpoint(breakpoint)) {
1226            try {
1227                ((JavaBreakpoint)breakpoint).removeFromTarget(this);
1228                getBreakpoints().remove(breakpoint);
1229                Iterator JavaDoc threads = getThreadIterator();
1230                while (threads.hasNext()) {
1231                    ((JDIThread)threads.next()).removeCurrentBreakpoint(breakpoint);
1232                }
1233            } catch (CoreException e) {
1234                logError(e);
1235            }
1236        }
1237    }
1238
1239    /**
1240     * @see ISuspendResume
1241     */

1242    public void suspend() throws DebugException {
1243        if (isSuspended()) {
1244            return;
1245        }
1246        try {
1247            VirtualMachine vm = getVM();
1248            if (vm != null) {
1249                vm.suspend();
1250            }
1251            suspendThreads();
1252            setSuspended(true);
1253            fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
1254        } catch (RuntimeException JavaDoc e) {
1255            setSuspended(false);
1256            fireResumeEvent(DebugEvent.CLIENT_REQUEST);
1257            targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIDebugTarget_exception_suspend, new String JavaDoc[] {e.toString()}), e);
1258        }
1259        
1260    }
1261    
1262    /**
1263     * Notifies threads that they have been suspended
1264     */

1265    protected void suspendThreads() {
1266        Iterator JavaDoc threads = getThreadIterator();
1267        while (threads.hasNext()) {
1268            ((JDIThread)threads.next()).suspendedByVM();
1269        }
1270    }
1271
1272    /**
1273     * Notifies threads that they have been resumed
1274     */

1275    protected void resumeThreads() throws DebugException {
1276        Iterator JavaDoc threads = getThreadIterator();
1277        while (threads.hasNext()) {
1278            ((JDIThread)threads.next()).resumedByVM();
1279        }
1280    }
1281    
1282    /**
1283     * Notifies this VM to update its state in preparation
1284     * for a suspend.
1285     *
1286     * @param breakpoint the breakpoint that caused the
1287     * suspension
1288     */

1289    public void prepareToSuspendByBreakpoint(JavaBreakpoint breakpoint) {
1290        setSuspended(true);
1291        suspendThreads();
1292    }
1293    
1294    /**
1295     * Notifies this VM it has been suspended by the
1296     * given breakpoint
1297     *
1298     * @param breakpoint the breakpoint that caused the
1299     * suspension
1300     */

1301    protected void suspendedByBreakpoint(JavaBreakpoint breakpoint, boolean queueEvent) {
1302        if (queueEvent) {
1303            queueSuspendEvent(DebugEvent.BREAKPOINT);
1304        } else {
1305            fireSuspendEvent(DebugEvent.BREAKPOINT);
1306        }
1307    }
1308    
1309    /**
1310     * Notifies this VM suspension has been cancelled
1311     *
1312     * @param breakpoint the breakpoint that caused the
1313     * suspension
1314     */

1315    protected void cancelSuspendByBreakpoint(JavaBreakpoint breakpoint) throws DebugException {
1316        setSuspended(false);
1317        resumeThreads();
1318    }
1319
1320    /**
1321     * @see ITerminate#terminate()
1322     */

1323    public void terminate() throws DebugException {
1324        if (!isAvailable()) {
1325            return;
1326        }
1327        if (!supportsTerminate()) {
1328            notSupported(JDIDebugModelMessages.JDIDebugTarget_does_not_support_termination);
1329        }
1330        try {
1331            setTerminating(true);
1332            disposeThreadHandler();
1333            VirtualMachine vm = getVM();
1334            if (vm != null) {
1335                vm.exit(1);
1336            }
1337            IProcess process= getProcess();
1338            if (process != null) {
1339                process.terminate();
1340            }
1341        } catch (VMDisconnectedException e) {
1342            // if the VM disconnects while exiting, perform
1343
// normal termination processing
1344
terminated();
1345        } catch (TimeoutException exception) {
1346            // if there is a timeout see if the associated process is terminated
1347
IProcess process = getProcess();
1348            if (process != null && process.isTerminated()) {
1349                terminated();
1350            } else {
1351                // All we can do is disconnect
1352
disconnected();
1353            }
1354        } catch (RuntimeException JavaDoc e) {
1355            targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIDebugTarget_exception_terminating, new String JavaDoc[] {e.toString()}), e);
1356        }
1357    }
1358
1359    /**
1360     * Updates the state of this target to be terminated,
1361     * if not already terminated.
1362     */

1363    protected void terminated() {
1364        setTerminating(false);
1365        if (!isTerminated()) {
1366            setTerminated(true);
1367            setDisconnected(true);
1368            cleanup();
1369            fireTerminateEvent();
1370        }
1371    }
1372    
1373    /**
1374     * Updates the state of this target for disconnection
1375     * from the VM.
1376     */

1377    protected void disconnected() {
1378        if (!isDisconnected()) {
1379            setDisconnected(true);
1380            cleanup();
1381            fireTerminateEvent();
1382        }
1383    }
1384
1385    /**
1386     * Cleans up the internal state of this debug
1387     * target as a result of a session ending with a
1388     * VM (as a result of a disconnect or termination of
1389     * the VM).
1390     * <p>
1391     * All threads are removed from this target.
1392     * This target is removed as a breakpoint listener,
1393     * and all breakpoints are removed from this target.
1394     * </p>
1395     */

1396    protected void cleanup() {
1397        removeAllThreads();
1398        DebugPlugin plugin = DebugPlugin.getDefault();
1399        plugin.getBreakpointManager().removeBreakpointListener(this);
1400        plugin.getLaunchManager().removeLaunchListener(this);
1401        plugin.getBreakpointManager().removeBreakpointManagerListener(this);
1402        plugin.removeDebugEventListener(this);
1403        removeAllBreakpoints();
1404        fOutOfSynchTypes.clear();
1405        if (fEngines != null) {
1406            Iterator JavaDoc engines = fEngines.values().iterator();
1407            while (engines.hasNext()) {
1408                IAstEvaluationEngine engine = (IAstEvaluationEngine)engines.next();
1409                engine.dispose();
1410            }
1411            fEngines.clear();
1412        }
1413        fVirtualMachine= null;
1414        setThreadStartHandler(null);
1415        setEventDispatcher(null);
1416        setStepFilters(new String JavaDoc[0]);
1417    }
1418
1419    /**
1420     * Removes all threads from this target's collection
1421     * of threads, firing a terminate event for each.
1422     */

1423    protected void removeAllThreads() {
1424        Iterator JavaDoc itr= getThreadIterator();
1425        while (itr.hasNext()) {
1426            JDIThread child= (JDIThread) itr.next();
1427            child.terminated();
1428        }
1429        synchronized (fThreads) {
1430            fThreads.clear();
1431        }
1432    }
1433
1434    /**
1435     * Removes all breakpoints from this target, such
1436     * that each breakpoint can update its install
1437     * count. This target's collection of breakpoints
1438     * is cleared.
1439     */

1440    protected void removeAllBreakpoints() {
1441        Iterator JavaDoc breakpoints= ((ArrayList JavaDoc)((ArrayList JavaDoc)getBreakpoints()).clone()).iterator();
1442        while (breakpoints.hasNext()) {
1443            JavaBreakpoint breakpoint= (JavaBreakpoint) breakpoints.next();
1444            try {
1445                breakpoint.removeFromTarget(this);
1446            } catch (CoreException e) {
1447                logError(e);
1448            }
1449        }
1450        getBreakpoints().clear();
1451    }
1452    
1453    /**
1454     * Adds all the breakpoints in this target's collection
1455     * to this debug target.
1456     */

1457    protected void reinstallAllBreakpoints() {
1458        Iterator JavaDoc breakpoints= ((ArrayList JavaDoc)((ArrayList JavaDoc)getBreakpoints()).clone()).iterator();
1459        while (breakpoints.hasNext()) {
1460            JavaBreakpoint breakpoint= (JavaBreakpoint) breakpoints.next();
1461            try {
1462                breakpoint.addToTarget(this);
1463            } catch (CoreException e) {
1464                logError(e);
1465            }
1466        }
1467    }
1468
1469    /**
1470     * Returns VirtualMachine.classesByName(String),
1471     * logging any JDI exceptions.
1472     *
1473     * @see com.sun.jdi.VirtualMachine
1474     */

1475    public List JavaDoc jdiClassesByName(String JavaDoc className) {
1476        VirtualMachine vm = getVM();
1477        if (vm != null) {
1478            try {
1479                return vm.classesByName(className);
1480            } catch (VMDisconnectedException e) {
1481                if (!isAvailable()) {
1482                    return Collections.EMPTY_LIST;
1483                }
1484                logError(e);
1485            } catch (RuntimeException JavaDoc e) {
1486                internalError(e);
1487            }
1488        }
1489        return Collections.EMPTY_LIST;
1490    }
1491
1492    /**
1493     * @see IJavaDebugTarget#findVariable(String)
1494     */

1495    public IJavaVariable findVariable(String JavaDoc varName) throws DebugException {
1496        IThread[] threads = getThreads();
1497        for (int i = 0; i < threads.length; i++) {
1498            IJavaThread thread = (IJavaThread)threads[i];
1499            IJavaVariable var = thread.findVariable(varName);
1500            if (var != null) {
1501                return var;
1502            }
1503        }
1504        return null;
1505    }
1506    
1507    /**
1508     * @see IAdaptable#getAdapter(Class)
1509     */

1510    public Object JavaDoc getAdapter(Class JavaDoc adapter) {
1511        if (adapter == IJavaDebugTarget.class) {
1512            return this;
1513        }
1514        return super.getAdapter(adapter);
1515    }
1516    
1517    /**
1518     * The JDIDebugPlugin is shutting down.
1519     * Shutdown the event dispatcher and do local
1520     * cleanup.
1521     */

1522    public void shutdown() {
1523        EventDispatcher dispatcher = ((JDIDebugTarget)getDebugTarget()).getEventDispatcher();
1524        if (dispatcher != null) {
1525            dispatcher.shutdown();
1526        }
1527        try {
1528            if (supportsTerminate()) {
1529                terminate();
1530            } else if (supportsDisconnect()) {
1531                disconnect();
1532            }
1533        } catch (DebugException e) {
1534            JDIDebugPlugin.log(e);
1535        }
1536        cleanup();
1537    }
1538    
1539    /**
1540     * Returns the CRC-32 of the entire class file contents associated with
1541     * given type, on the target VM, or <code>null</code> if the type is
1542     * not loaded, or a CRC for the type is not known.
1543     *
1544     * @param typeName fully qualified name of the type for which a
1545     * CRC is required. For example, "com.example.Example".
1546     * @return 32 bit CRC, or <code>null</code>
1547     * @exception DebugException if this method fails. Reasons include:
1548     * <ul>
1549     * <li>Failure communicating with the VM. The DebugException's
1550     * status code contains the underlying exception responsible for
1551     * the failure.</li>
1552     * </ul>
1553     */

1554    protected Integer JavaDoc getCRC(String JavaDoc typeName) throws DebugException {
1555        if (getVM() instanceof org.eclipse.jdi.hcr.VirtualMachine) {
1556            List JavaDoc classes = jdiClassesByName(typeName);
1557            if (!classes.isEmpty()) {
1558                ReferenceType type = (ReferenceType)classes.get(0);
1559                if (type instanceof org.eclipse.jdi.hcr.ReferenceType) {
1560                    try {
1561                        org.eclipse.jdi.hcr.ReferenceType rt = (org.eclipse.jdi.hcr.ReferenceType)type;
1562                        if (rt.isVersionKnown()) {
1563                            return new Integer JavaDoc(rt.getClassFileVersion());
1564                        }
1565                    } catch (RuntimeException JavaDoc e) {
1566                        targetRequestFailed(MessageFormat.format(JDIDebugModelMessages.JDIDebugTarget_exception_retrieving_version_information, new String JavaDoc[] {e.toString(), type.name()}), e);
1567                        // execution will never reach this line, as
1568
// #targetRequestFailed will throw an exception
1569
return null;
1570                    }
1571                }
1572            }
1573        }
1574        return null;
1575    }
1576
1577    /**
1578     * @see IJavaDebugTarget#getJavaTypes(String)
1579     */

1580    public IJavaType[] getJavaTypes(String JavaDoc name) throws DebugException {
1581        try {
1582            // get java.lang.Class
1583
VirtualMachine vm = getVM();
1584            if (vm == null) {
1585                requestFailed(JDIDebugModelMessages.JDIDebugTarget_Unable_to_retrieve_types___VM_disconnected__4, null);
1586            }
1587            List JavaDoc classes = vm.classesByName(name);
1588            if (classes.size() == 0) {
1589                switch (name.charAt(0)) {
1590                    case 'b':
1591                        if (name.equals("boolean")) { //$NON-NLS-1$
1592
return new IJavaType[] {newValue(true).getJavaType()};
1593                        } else if (name.equals("byte")) { //$NON-NLS-1$
1594
return new IJavaType[] {newValue((byte)1).getJavaType()};
1595                        }
1596                        break;
1597                    case 'i':
1598                        if (name.equals("int")) { //$NON-NLS-1$
1599
return new IJavaType[] {newValue(1).getJavaType()};
1600                        }
1601                        break;
1602                    case 'l':
1603                        if (name.equals("long")) { //$NON-NLS-1$
1604
return new IJavaType[] {newValue(1l).getJavaType()};
1605                        }
1606                        break;
1607                    case 'c':
1608                        if (name.equals("char")) { //$NON-NLS-1$
1609
return new IJavaType[] {newValue(' ').getJavaType()};
1610                        }
1611                        break;
1612                    case 's':
1613                        if (name.equals("short")) { //$NON-NLS-1$
1614
return new IJavaType[] {newValue((short)1).getJavaType()};
1615                        }
1616                        break;
1617                    case 'f':
1618                        if (name.equals("float")) { //$NON-NLS-1$
1619
return new IJavaType[] {newValue(1f).getJavaType()};
1620                        }
1621                        break;
1622                    case 'd':
1623                        if (name.equals("double")) { //$NON-NLS-1$
1624
return new IJavaType[] {newValue(1d).getJavaType()};
1625                        }
1626                        break;
1627                }
1628                return null;
1629            }
1630            IJavaType[] types = new IJavaType[classes.size()];
1631            for (int i = 0; i < types.length; i++) {
1632                types[i] = JDIType.createType(this, (Type)classes.get(i));
1633            }
1634            return types;
1635        } catch (RuntimeException JavaDoc e) {
1636            targetRequestFailed(MessageFormat.format("{0} occurred while retrieving class for name {1}", new String JavaDoc[]{e.toString(), name}), e); //$NON-NLS-1$
1637
// execution will not reach this line, as
1638
// #targetRequestFailed will throw an exception
1639
return null;
1640        }
1641    }
1642    
1643    /**
1644     * @see IJavaDebugTarget#newValue(boolean)
1645     */

1646    public IJavaValue newValue(boolean value) {
1647        VirtualMachine vm = getVM();
1648        if (vm != null) {
1649            Value v = vm.mirrorOf(value);
1650            return JDIValue.createValue(this, v);
1651        }
1652        return null;
1653    }
1654    
1655    /**
1656     * @see IJavaDebugTarget#newValue(byte)
1657     */

1658    public IJavaValue newValue(byte value) {
1659        VirtualMachine vm = getVM();
1660        if (vm != null) {
1661            Value v = vm.mirrorOf(value);
1662            return JDIValue.createValue(this, v);
1663        }
1664        return null;
1665    }
1666
1667    /**
1668     * @see IJavaDebugTarget#newValue(char)
1669     */

1670    public IJavaValue newValue(char value) {
1671        VirtualMachine vm = getVM();
1672        if (vm != null) {
1673            Value v = vm.mirrorOf(value);
1674            return JDIValue.createValue(this, v);
1675        }
1676        return null;
1677    }
1678
1679    /**
1680     * @see IJavaDebugTarget#newValue(double)
1681     */

1682    public IJavaValue newValue(double value) {
1683        VirtualMachine vm = getVM();
1684        if (vm != null) {
1685            Value v = vm.mirrorOf(value);
1686            return JDIValue.createValue(this, v);
1687        }
1688        return null;
1689    }
1690    
1691    /**
1692     * @see IJavaDebugTarget#newValue(float)
1693     */

1694    public IJavaValue newValue(float value) {
1695        VirtualMachine vm = getVM();
1696        if (vm != null) {
1697            Value v = vm.mirrorOf(value);
1698            return JDIValue.createValue(this, v);
1699        }
1700        return null;
1701    }
1702                        
1703    /**
1704     * @see IJavaDebugTarget#newValue(int)
1705     */

1706    public IJavaValue newValue(int value) {
1707        VirtualMachine vm = getVM();
1708        if (vm != null) {
1709            Value v = vm.mirrorOf(value);
1710            return JDIValue.createValue(this, v);
1711        }
1712        return null;
1713    }
1714    
1715    /**
1716     * @see IJavaDebugTarget#newValue(long)
1717     */

1718    public IJavaValue newValue(long value) {
1719        VirtualMachine vm = getVM();
1720        if (vm != null) {
1721            Value v = vm.mirrorOf(value);
1722            return JDIValue.createValue(this, v);
1723        }
1724        return null;
1725    }
1726    
1727    /**
1728     * @see IJavaDebugTarget#newValue(short)
1729     */

1730    public IJavaValue newValue(short value) {
1731        VirtualMachine vm = getVM();
1732        if (vm != null) {
1733            Value v = vm.mirrorOf(value);
1734            return JDIValue.createValue(this, v);
1735        }
1736        return null;
1737    }
1738    
1739    /**
1740     * @see IJavaDebugTarget#newValue(String)
1741     */

1742    public IJavaValue newValue(String JavaDoc value) {
1743        VirtualMachine vm = getVM();
1744        if (vm != null) {
1745            Value v = vm.mirrorOf(value);
1746            return JDIValue.createValue(this, v);
1747        }
1748        return null;
1749    }
1750        
1751    /**
1752     * @see IJavaDebugTarget#nullValue()
1753     */

1754    public IJavaValue nullValue() {
1755        return JDIValue.createValue(this, null);
1756    }
1757    
1758    /**
1759     * @see IJavaDebugTarget#voidValue()
1760     */

1761    public IJavaValue voidValue() {
1762        return new JDIVoidValue(this);
1763    }
1764    
1765    protected boolean isTerminating() {
1766        return fTerminating;
1767    }
1768
1769    protected void setTerminating(boolean terminating) {
1770        fTerminating = terminating;
1771    }
1772        
1773    /**
1774     * An event handler for thread start events. When a thread
1775     * starts in the target VM, a model thread is created.
1776     */

1777    class ThreadStartHandler implements IJDIEventListener {
1778        
1779        protected EventRequest fRequest;
1780        
1781        protected ThreadStartHandler() {
1782            createRequest();
1783        }
1784        
1785        /**
1786         * Creates and registers a request to handle all thread start
1787         * events
1788         */

1789        protected void createRequest() {
1790            EventRequestManager manager = getEventRequestManager();
1791            if (manager != null) {
1792                try {
1793                    EventRequest req= manager.createThreadStartRequest();
1794                    req.setSuspendPolicy(EventRequest.SUSPEND_NONE);
1795                    req.enable();
1796                    addJDIEventListener(this, req);
1797                    setRequest(req);
1798                } catch (RuntimeException JavaDoc e) {
1799                    logError(e);
1800                }
1801            }
1802        }
1803
1804        /**
1805         * Creates a model thread for the underlying JDI thread
1806         * and adds it to the collection of threads for this
1807         * debug target. As a side effect of creating the thread,
1808         * a create event is fired for the model thread.
1809         * The event is ignored if the underlying thread is already
1810         * marked as collected.
1811         *
1812         * @param event a thread start event
1813         * @param target the target in which the thread started
1814         * @return <code>true</code> - the thread should be resumed
1815         */

1816        public boolean handleEvent(Event event, JDIDebugTarget target) {
1817            ThreadReference thread= ((ThreadStartEvent)event).thread();
1818            try {
1819                if (thread.isCollected()) {
1820                    return false;
1821                }
1822            } catch (VMDisconnectedException exception) {
1823                return false;
1824            } catch (ObjectCollectedException e) {
1825                return false;
1826            } catch (TimeoutException e) {
1827                // continue - attempt to create the thread
1828
}
1829            JDIThread jdiThread= findThread(thread);
1830            if (jdiThread == null) {
1831                jdiThread = createThread(thread);
1832                if (jdiThread == null) {
1833                    return false;
1834                }
1835            } else {
1836                jdiThread.disposeStackFrames();
1837                jdiThread.fireChangeEvent(DebugEvent.CONTENT);
1838            }
1839            return !jdiThread.isSuspended();
1840        }
1841
1842        /* (non-Javadoc)
1843         * @see org.eclipse.jdt.internal.debug.core.IJDIEventListener#wonSuspendVote(com.sun.jdi.event.Event, org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget)
1844         */

1845        public void wonSuspendVote(Event event, JDIDebugTarget target) {
1846            // do nothing
1847
}
1848        
1849        /**
1850         * De-registers this event listener.
1851         */

1852        protected void deleteRequest() {
1853            if (getRequest() != null) {
1854                removeJDIEventListener(this, getRequest());
1855                setRequest(null);
1856            }
1857        }
1858        
1859        protected EventRequest getRequest() {
1860            return fRequest;
1861        }
1862
1863        protected void setRequest(EventRequest request) {
1864            fRequest = request;
1865        }
1866}
1867    
1868    /**
1869     * An event handler for thread death events. When a thread
1870     * dies in the target VM, its associated model thread is
1871     * removed from the debug target.
1872     */

1873    class ThreadDeathHandler implements IJDIEventListener {
1874        
1875        protected ThreadDeathHandler() {
1876            createRequest();
1877        }
1878        
1879        /**
1880         * Creates and registers a request to listen to thread
1881         * death events.
1882         */

1883        protected void createRequest() {
1884            EventRequestManager manager = getEventRequestManager();
1885            if (manager != null) {
1886                try {
1887                    EventRequest req= manager.createThreadDeathRequest();
1888                    req.setSuspendPolicy(EventRequest.SUSPEND_NONE);
1889                    req.enable();
1890                    addJDIEventListener(this, req);
1891                } catch (RuntimeException JavaDoc e) {
1892                    logError(e);
1893                }
1894            }
1895        }
1896                
1897        /**
1898         * Locates the model thread associated with the underlying JDI thread
1899         * that has terminated, and removes it from the collection of
1900         * threads belonging to this debug target. A terminate event is
1901         * fired for the model thread.
1902         *
1903         * @param event a thread death event
1904         * @param target the target in which the thread died
1905         * @return <code>true</code> - the thread should be resumed
1906         */

1907        public boolean handleEvent(Event event, JDIDebugTarget target) {
1908            ThreadReference ref= ((ThreadDeathEvent)event).thread();
1909            JDIThread thread= findThread(ref);
1910            if (thread != null) {
1911                synchronized (fThreads) {
1912                    fThreads.remove(thread);
1913                }
1914                thread.terminated();
1915            }
1916            return true;
1917        }
1918        
1919        /* (non-Javadoc)
1920         * @see org.eclipse.jdt.internal.debug.core.IJDIEventListener#wonSuspendVote(com.sun.jdi.event.Event, org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget)
1921         */

1922        public void wonSuspendVote(Event event, JDIDebugTarget target) {
1923            // do nothing
1924
}
1925    
1926    }
1927    
1928    class CleanUpJob extends Job {
1929
1930        /**
1931         * Constructs a job to cleanup a hanging target.
1932         */

1933        public CleanUpJob() {
1934            super(JDIDebugModelMessages.JDIDebugTarget_0);
1935            setSystem(true);
1936        }
1937
1938        /* (non-Javadoc)
1939         * @see org.eclipse.core.internal.jobs.InternalJob#run(org.eclipse.core.runtime.IProgressMonitor)
1940         */

1941        protected IStatus run(IProgressMonitor monitor) {
1942            if (isAvailable()) {
1943                if (fEventDispatcher != null) {
1944                    fEventDispatcher.shutdown();
1945                }
1946                disconnected();
1947            }
1948            return Status.OK_STATUS;
1949        }
1950
1951        /* (non-Javadoc)
1952         * @see org.eclipse.core.runtime.jobs.Job#shouldRun()
1953         */

1954        public boolean shouldRun() {
1955            return isAvailable();
1956        }
1957
1958        /* (non-Javadoc)
1959         * @see org.eclipse.core.internal.jobs.InternalJob#shouldSchedule()
1960         */

1961        public boolean shouldSchedule() {
1962            return isAvailable();
1963        }
1964        
1965        
1966    }
1967    
1968    protected ThreadStartHandler getThreadStartHandler() {
1969        return fThreadStartHandler;
1970    }
1971
1972    protected void setThreadStartHandler(ThreadStartHandler threadStartHandler) {
1973        fThreadStartHandler = threadStartHandler;
1974    }
1975    
1976    /**
1977     * Java debug targets do not support storage retrieval.
1978     *
1979     * @see IMemoryBlockRetrieval#supportsStorageRetrieval()
1980     */

1981    public boolean supportsStorageRetrieval() {
1982        return false;
1983    }
1984
1985    /**
1986     * @see IMemoryBlockRetrieval#getMemoryBlock(long, long)
1987     */

1988    public IMemoryBlock getMemoryBlock(long startAddress, long length)
1989        throws DebugException {
1990            notSupported(JDIDebugModelMessages.JDIDebugTarget_does_not_support_storage_retrieval);
1991            // this line will not be executed as #notSupported(String)
1992
// will throw an exception
1993
return null;
1994    }
1995
1996    /**
1997     * @see ILaunchListener#launchRemoved(ILaunch)
1998     */

1999    public void launchRemoved(ILaunch launch) {
2000        if (!isAvailable()) {
2001            return;
2002        }
2003        if (launch.equals(getLaunch())) {
2004            // This target has been de-registered, but it hasn't successfully terminated.
2005
// Update internal state to reflect that it is disconnected
2006
disconnected();
2007        }
2008    }
2009
2010    /**
2011     * @see ILaunchListener#launchAdded(ILaunch)
2012     */

2013    public void launchAdded(ILaunch launch) {
2014    }
2015    
2016    /**
2017     * @see ILaunchListener#launchChanged(ILaunch)
2018     */

2019    public void launchChanged(ILaunch launch) {
2020    }
2021
2022    /**
2023     * Sets whether the VM should be resumed on startup.
2024     * Has no effect if the VM is already running when
2025     * this target is created.
2026     *
2027     * @param resume whether the VM should be resumed on startup
2028     */

2029    private synchronized void setResumeOnStartup(boolean resume) {
2030        fResumeOnStartup = resume;
2031    }
2032    
2033    /**
2034     * Returns whether this VM should be resumed on startup.
2035     *
2036     * @return whether this VM should be resumed on startup
2037     */

2038    protected synchronized boolean isResumeOnStartup() {
2039        return fResumeOnStartup;
2040    }
2041    
2042    /**
2043     * @see IJavaDebugTarget#getStepFilters()
2044     */

2045    public String JavaDoc[] getStepFilters() {
2046        return fStepFilters;
2047    }
2048
2049    /**
2050     * @see IJavaDebugTarget#isFilterConstructors()
2051     */

2052    public boolean isFilterConstructors() {
2053        return (fStepFilterMask & FILTER_CONSTRUCTORS) > 0;
2054    }
2055
2056    /**
2057     * @see IJavaDebugTarget#isFilterStaticInitializers()
2058     */

2059    public boolean isFilterStaticInitializers() {
2060        return (fStepFilterMask & FILTER_STATIC_INITIALIZERS) > 0;
2061    }
2062
2063    /**
2064     * @see IJavaDebugTarget#isFilterSynthetics()
2065     */

2066    public boolean isFilterSynthetics() {
2067        return (fStepFilterMask & FILTER_SYNTHETICS) > 0;
2068    }
2069    
2070    /**
2071     * Returns whether steps that land in filtered location should
2072     * proceed through to an un-filtered location or return.
2073     *
2074     * @return whether steps that land in filtered location should
2075     * proceed through to an un-filtered location or return
2076     * @since 3.3
2077     * TODO: make API once API freeze is over
2078     */

2079    public boolean isStepThruFilters() {
2080        return (fStepFilterMask & STEP_THRU_FILTERS) > 0;
2081    }
2082
2083    /**
2084     * @see IJavaDebugTarget#isStepFiltersEnabled()
2085     */

2086    public boolean isStepFiltersEnabled() {
2087        return (fStepFilterMask & STEP_FILTERS_ENABLED) > 0;
2088    }
2089
2090    /**
2091     * @see IJavaDebugTarget#setFilterConstructors(boolean)
2092     */

2093    public void setFilterConstructors(boolean filter) {
2094        if (filter) {
2095            fStepFilterMask = fStepFilterMask | FILTER_CONSTRUCTORS;
2096        } else {
2097            fStepFilterMask = fStepFilterMask & (FILTER_CONSTRUCTORS ^ XOR_MASK);
2098        }
2099    }
2100
2101    /**
2102     * @see IJavaDebugTarget#setFilterStaticInitializers(boolean)
2103     */

2104    public void setFilterStaticInitializers(boolean filter) {
2105        if (filter) {
2106            fStepFilterMask = fStepFilterMask | FILTER_STATIC_INITIALIZERS;
2107        } else {
2108            fStepFilterMask = fStepFilterMask & (FILTER_STATIC_INITIALIZERS ^ XOR_MASK);
2109        }
2110    }
2111
2112    /**
2113     * @see IJavaDebugTarget#setFilterSynthetics(boolean)
2114     */

2115    public void setFilterSynthetics(boolean filter) {
2116        if (filter) {
2117            fStepFilterMask = fStepFilterMask | FILTER_SYNTHETICS;
2118        } else {
2119            fStepFilterMask = fStepFilterMask & (FILTER_SYNTHETICS ^ XOR_MASK);
2120        }
2121    }
2122    
2123    /**
2124     * Sets whether a step that lands in a filtered location should continue through
2125     * to an un-filtered location, or return to where the step originated.
2126     *
2127     * @param thru whether to step thru
2128     * @since 3.3
2129     * TODO: make API once API freeze is over
2130     */

2131    public void setStepThruFilters(boolean thru) {
2132        if (thru) {
2133            fStepFilterMask = fStepFilterMask | STEP_THRU_FILTERS;
2134        } else {
2135            fStepFilterMask = fStepFilterMask & (STEP_THRU_FILTERS ^ XOR_MASK);
2136        }
2137    }
2138
2139    /**
2140     * @see IJavaDebugTarget#setStepFilters(String[])
2141     */

2142    public void setStepFilters(String JavaDoc[] list) {
2143        fStepFilters = list;
2144    }
2145
2146    /**
2147     * @see IJavaDebugTarget#setStepFiltersEnabled(boolean)
2148     */

2149    public void setStepFiltersEnabled(boolean enabled) {
2150        if (enabled) {
2151            fStepFilterMask = fStepFilterMask | STEP_FILTERS_ENABLED;
2152        } else {
2153            fStepFilterMask = fStepFilterMask & (STEP_FILTERS_ENABLED ^ XOR_MASK);
2154        }
2155    }
2156
2157    /**
2158     * @see IDebugTarget#hasThreads()
2159     */

2160    public boolean hasThreads() {
2161        return fThreads.size() > 0;
2162    }
2163    
2164    /**
2165     * @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
2166     */

2167    public ILaunch getLaunch() {
2168        return fLaunch;
2169    }
2170
2171    /**
2172     * Sets the launch this target is contained in
2173     *
2174     * @param launch the launch this target is contained in
2175     */

2176    private void setLaunch(ILaunch launch) {
2177        fLaunch = launch;
2178    }
2179    
2180    /**
2181     * Returns the number of suspend events that have occurred in this
2182     * target.
2183     *
2184     * @return the number of suspend events that have occurred in this
2185     * target
2186     */

2187    protected int getSuspendCount() {
2188        return fSuspendCount;
2189    }
2190    
2191    /**
2192     * Increments the suspend counter for this target based on the reason
2193     * for the suspend event. The suspend count is not updated for
2194     * implicit evaluations.
2195     *
2196     * @param eventDetail the reason for the suspend event
2197     */

2198    protected void incrementSuspendCount(int eventDetail) {
2199        if (eventDetail != DebugEvent.EVALUATION_IMPLICIT) {
2200            fSuspendCount++;
2201        }
2202    }
2203    
2204    /**
2205     * Returns an evaluation engine for the given project, creating
2206     * one if necessary.
2207     *
2208     * @param project java project
2209     * @return evaluation engine
2210     */

2211    public IAstEvaluationEngine getEvaluationEngine(IJavaProject project) {
2212        if (fEngines == null) {
2213            fEngines = new HashMap JavaDoc(2);
2214        }
2215        IAstEvaluationEngine engine = (IAstEvaluationEngine)fEngines.get(project);
2216        if (engine == null) {
2217            engine = EvaluationManager.newAstEvaluationEngine(project, this);
2218            fEngines.put(project, engine);
2219        }
2220        return engine;
2221    }
2222    
2223    /**
2224     * @see org.eclipse.jdt.debug.core.IJavaDebugTarget#supportsMonitorInformation()
2225     */

2226    public boolean supportsMonitorInformation() {
2227        if (!isAvailable()) {
2228            return false;
2229        }
2230        VirtualMachine vm = getVM();
2231        if (vm != null) {
2232            return vm.canGetCurrentContendedMonitor() && vm.canGetMonitorInfo() && vm.canGetOwnedMonitorInfo();
2233        }
2234        return false;
2235    }
2236    
2237    /**
2238     * Sets whether or not this debug target is currently performing a hot code
2239     * replace.
2240     */

2241    public void setIsPerformingHotCodeReplace(boolean isPerformingHotCodeReplace) {
2242        fIsPerformingHotCodeReplace= isPerformingHotCodeReplace;
2243    }
2244    
2245    /**
2246     * @see IJavaDebugTarget#isPerformingHotCodeReplace()
2247     */

2248    public boolean isPerformingHotCodeReplace() {
2249        return fIsPerformingHotCodeReplace;
2250    }
2251    
2252    /* (non-Javadoc)
2253     * @see org.eclipse.jdt.debug.core.IJavaDebugTarget#supportsAccessWatchpoints()
2254     */

2255    public boolean supportsAccessWatchpoints() {
2256        VirtualMachine vm = getVM();
2257        if (isAvailable() && vm != null) {
2258            return vm.canWatchFieldAccess();
2259        }
2260        return false;
2261    }
2262
2263    /* (non-Javadoc)
2264     * @see org.eclipse.jdt.debug.core.IJavaDebugTarget#supportsModificationWatchpoints()
2265     */

2266    public boolean supportsModificationWatchpoints() {
2267        VirtualMachine vm = getVM();
2268        if (isAvailable() && vm != null) {
2269            return vm.canWatchFieldModification();
2270        }
2271        return false;
2272    }
2273
2274    /**
2275     * @see org.eclipse.jdt.debug.core.IJavaDebugTarget#setDefaultStratum()
2276     */

2277    public void setDefaultStratum(String JavaDoc stratum) {
2278        VirtualMachine vm = getVM();
2279        if (vm != null) {
2280            vm.setDefaultStratum(stratum);
2281        }
2282    }
2283    
2284    public String JavaDoc getDefaultStratum() {
2285        VirtualMachine vm = getVM();
2286        if (vm != null) {
2287            return vm.getDefaultStratum();
2288        }
2289        return null;
2290    }
2291
2292    /* (non-Javadoc)
2293     * @see org.eclipse.debug.core.model.IStepFilters#supportsStepFilters()
2294     */

2295    public boolean supportsStepFilters() {
2296        return isAvailable();
2297    }
2298
2299    /**
2300     * When the breakpoint manager disables, remove all registered breakpoints
2301     * requests from the VM. When it enables, reinstall them.
2302     */

2303    public void breakpointManagerEnablementChanged(boolean enabled) {
2304        if (!isAvailable()) {
2305            return;
2306        }
2307        Iterator JavaDoc breakpoints= ((ArrayList JavaDoc)((ArrayList JavaDoc)getBreakpoints()).clone()).iterator();
2308        while (breakpoints.hasNext()) {
2309            JavaBreakpoint breakpoint= (JavaBreakpoint) breakpoints.next();
2310            try {
2311                if (enabled) {
2312                    breakpoint.addToTarget(this);
2313                } else if (breakpoint.shouldSkipBreakpoint()) {
2314                    breakpoint.removeFromTarget(this);
2315                }
2316            } catch (CoreException e) {
2317                logError(e);
2318            }
2319        }
2320    }
2321
2322    /* (non-Javadoc)
2323     * @see org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse.debug.core.DebugEvent[])
2324     */

2325    public void handleDebugEvents(DebugEvent[] events) {
2326        if (events.length == 1) {
2327            DebugEvent event = events[0];
2328            if (event.getSource().equals(getProcess()) && event.getKind() == DebugEvent.TERMINATE) {
2329                // schedule a job to clean up the target in case we never get a terminate/disconnect
2330
// event from the VM
2331
int timeout = getRequestTimeout();
2332                if (timeout < 0) {
2333                    timeout = 3000;
2334                }
2335                new CleanUpJob().schedule(timeout);
2336            }
2337        }
2338    }
2339    
2340    /* (non-Javadoc)
2341     * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget()
2342     */

2343    public IDebugTarget getDebugTarget() {
2344        return this;
2345    }
2346    
2347    /**
2348     * Adds the given thread group to the list of known thread groups. Also adds any parent thread groups
2349     * that have not already been added to the list.
2350     *
2351     * @param group thread group to add
2352     */

2353    void addThreadGroup(ThreadGroupReference group) {
2354        ThreadGroupReference currentGroup = group;
2355        while(currentGroup != null){
2356            synchronized (fGroups) {
2357                if (findThreadGroup(currentGroup) == null) {
2358                    JDIThreadGroup modelGroup = new JDIThreadGroup(this, currentGroup);
2359                    fGroups.add(modelGroup);
2360                    currentGroup = currentGroup.parent();
2361                    // TODO: create event?
2362
} else {
2363                    currentGroup = null;
2364                }
2365            }
2366        }
2367    }
2368    
2369    JDIThreadGroup findThreadGroup(ThreadGroupReference group) {
2370        synchronized (fGroups) {
2371            Iterator JavaDoc groups = fGroups.iterator();
2372            while (groups.hasNext()) {
2373                JDIThreadGroup modelGroup = (JDIThreadGroup) groups.next();
2374                if (modelGroup.getUnderlyingThreadGroup().equals(group)) {
2375                    return modelGroup;
2376                }
2377            }
2378        }
2379        return null;
2380    }
2381
2382    /* (non-Javadoc)
2383     * @see org.eclipse.jdt.debug.core.IJavaDebugTarget#getThreadGroups()
2384     */

2385    public IJavaThreadGroup[] getRootThreadGroups() throws DebugException {
2386        try {
2387            VirtualMachine vm = getVM();
2388            if (vm == null) {
2389                return new IJavaThreadGroup[0];
2390            }
2391            List JavaDoc groups = vm.topLevelThreadGroups();
2392            List JavaDoc modelGroups = new ArrayList JavaDoc(groups.size());
2393            Iterator JavaDoc iterator = groups.iterator();
2394            while (iterator.hasNext()) {
2395                ThreadGroupReference ref = (ThreadGroupReference) iterator.next();
2396                JDIThreadGroup group = findThreadGroup(ref);
2397                if (group != null) {
2398                    modelGroups.add(group);
2399                }
2400            }
2401            return (IJavaThreadGroup[]) modelGroups.toArray(new IJavaThreadGroup[modelGroups.size()]);
2402        } catch (RuntimeException JavaDoc e) {
2403            targetRequestFailed(JDIDebugModelMessages.JDIDebugTarget_1, e);
2404        }
2405        return null;
2406    }
2407
2408    /* (non-Javadoc)
2409     * @see org.eclipse.jdt.debug.core.IJavaDebugTarget#getAllThreadGroups()
2410     */

2411    public IJavaThreadGroup[] getAllThreadGroups() throws DebugException {
2412        synchronized (fGroups) {
2413            return (IJavaThreadGroup[]) fGroups.toArray(new IJavaThreadGroup[fGroups.size()]);
2414        }
2415    }
2416
2417    /* (non-Javadoc)
2418     * @see org.eclipse.jdt.debug.core.IJavaDebugTarget#supportsInstanceRetrieval()
2419     */

2420    public boolean supportsInstanceRetrieval() {
2421        VirtualMachine vm = getVM();
2422        if (vm != null) {
2423            return vm.canGetInstanceInfo();
2424        }
2425        return false;
2426    }
2427    
2428    /**
2429     * Sends a JDWP command to the back end and returns the JDWP reply packet as bytes.
2430     * This method creates an appropriate command header and packet id, before sending
2431     * to the back end.
2432     *
2433     * @param commandSet command set identifier as defined by JDWP
2434     * @param commandId command identifier as defined by JDWP
2435     * @param data any bytes required for the command that follow the command header
2436     * or <code>null</code> for commands that have no data
2437     * @return raw reply packet as bytes defined by JDWP
2438     * @exception IOException if an error occurs sending the packet or receiving the reply
2439     * @since 3.3
2440     */

2441    public byte[] sendJDWPCommand(byte commandSet, byte commandId, byte[] data) throws IOException JavaDoc {
2442        int command = (256 * commandSet) + commandId;
2443        JdwpReplyPacket reply = ((VirtualMachineImpl)getVM()).requestVM(command, data);
2444        return reply.getPacketAsBytes();
2445    }
2446
2447    /* (non-Javadoc)
2448     * @see org.eclipse.jdt.debug.core.IJavaDebugTarget#supportsForceReturn()
2449     */

2450    public boolean supportsForceReturn() {
2451        VirtualMachine machine = getVM();
2452        if(machine == null) {
2453            return false;
2454        }
2455        return machine.canForceEarlyReturn();
2456    }
2457}
2458
Popular Tags