KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > util > Operator


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.debugger.jpda.util;
21
22 import com.sun.jdi.VirtualMachine;
23 import com.sun.jdi.VMDisconnectedException;
24 import com.sun.jdi.event.*;
25 import com.sun.jdi.request.EventRequest;
26 import com.sun.jdi.request.StepRequest;
27 import com.sun.jdi.ThreadReference;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.logging.Level JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
34 import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl;
35 import org.openide.ErrorManager;
36
37 /**
38  * Listens for events coming from a remove VM and notifies registered objects.
39  * <P>
40  * Any object implementing interface {@link Executor} can bind itself
41  * with an {@link EventRequest}. Each time an {@link Event} corresponding
42  * to the request comes from the virtual machine the <TT>Operator</TT>
43  * notifies the registered object by calling its <TT>exec()</TT> method.
44  * <P>
45  * The only exceptions to the above rule are <TT>VMStartEvent</TT>,
46  * <TT>VMDeathEvent</TT> and <TT>VMDisconnectEvent</TT> that cannot be
47  * bound to any request. To listen for these events, specify <EM>starter</EM>
48  * and <EM>finalizer</EM> in the constructor.
49  * <P>
50  * The operator is not active until it is started - use method <TT>start()</TT>.
51  * The operator stops itself when either <TT>VMDeathEvent</TT> or <TT>VMDisconnectEvent</TT>
52  * is received; it can be started again.
53  * <P>
54  * Use method {@link #register} to bind a requst with an object.
55  * The object can be unregistered - use method {@link #unregister}.
56  * <P>
57  * There should be only one <TT>Operator</TT> per remote VM.
58 *
59 * @author Jan Jancura
60 */

61 public class Operator {
62     
63     private static Logger JavaDoc logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.jdievents"); // NOI18N
64

65     private Thread JavaDoc thread;
66     private boolean breakpointsDisabled;
67     private List JavaDoc<EventSet> staledEvents = new ArrayList JavaDoc<EventSet>();
68     private List JavaDoc<EventRequest> staledRequests = new ArrayList JavaDoc<EventRequest>();
69     private boolean stop;
70
71     /**
72      * Creates an operator for a given virtual machine. The operator will listen
73      * to the VM's event queue.
74      *
75      * @param virtualMachine remote VM this operator will listen to
76      * @param starter thread to be started upon start of the remote VM
77      * (may be <TT>null</TT>)
78      * @param finalizer thread to be started upon death of the remote VM
79      * or upon disconnection from the VM
80      * (may be <TT>null</TT>)
81     */

82     public Operator (
83         VirtualMachine virtualMachine,
84         final JPDADebuggerImpl debugger,
85         Executor starter,
86         Runnable JavaDoc finalizer,
87         final Object JavaDoc resumeLock
88     ) {
89         EventQueue eventQueue = virtualMachine.eventQueue ();
90         if (eventQueue == null)
91             throw new NullPointerException JavaDoc ();
92         final Object JavaDoc[] params = new Object JavaDoc[] {eventQueue, starter, finalizer};
93         thread = new Thread JavaDoc (new Runnable JavaDoc () {
94         public void run () {
95             EventQueue eventQueue = (EventQueue) params [0];
96             Executor starter = (Executor) params [1];
97             Runnable JavaDoc finalizer = (Runnable JavaDoc) params [2];
98             params [0] = null;
99             params [1] = null;
100             params [2] = null;
101             boolean processStaledEvents = false;
102             
103              try {
104                  for (;;) {
105                      EventSet eventSet = null;
106                      if (processStaledEvents) {
107                          synchronized (Operator.this) {
108                              if (staledEvents.size() == 0) {
109                                  processStaledEvents = false;
110                              } else {
111                                 eventSet = staledEvents.remove(0);
112                                 while (staledRequests.size() > 0) {
113                                     EventRequest request = staledRequests.remove(0);
114                                     request.virtualMachine().eventRequestManager().deleteEventRequest(request);
115                                 }
116                                 //eventSet.virtualMachine.suspend();
117
}
118                          }
119                      }
120                      if (eventSet == null) {
121                         try {
122                             eventSet = eventQueue.remove ();
123                             if (logger.isLoggable(Level.FINE)) {
124                                 logger.fine("HAVE EVENT(s) in the Queue: "+eventSet);
125                             }
126                         } catch (InterruptedException JavaDoc iexc) {
127                             synchronized (Operator.this) {
128                                 if (stop) {
129                                     break;
130                                 }
131                             }
132                             processStaledEvents = true;
133                             continue;
134                         }
135                      }
136                      synchronized (Operator.this) {
137                          if (breakpointsDisabled) {
138                              if (eventSet.suspendPolicy() == EventRequest.SUSPEND_ALL) {
139                                 staledEvents.add(eventSet);
140                                 eventSet.resume();
141                                 if (logger.isLoggable(Level.FINE)) {
142                                     logger.fine("RESUMING "+eventSet);
143                                 }
144                              }
145                              continue;
146                          }
147                      }
148                      boolean resume = true, startEventOnly = true;
149                      int suspendPolicy = eventSet.suspendPolicy();
150                      boolean suspendedAll = suspendPolicy == EventRequest.SUSPEND_ALL;
151                      JPDAThreadImpl suspendedThread = null;
152                      if (suspendedAll) debugger.notifySuspendAll();
153                      if (suspendPolicy == EventRequest.SUSPEND_EVENT_THREAD) {
154                          EventIterator i = eventSet.eventIterator ();
155                          ThreadReference tref = null;
156                          while (i.hasNext ()) {
157                             Event e = i.nextEvent ();
158                             if (e instanceof LocatableEvent) {
159                                 tref = ((LocatableEvent) e).thread();
160                                 break;
161                             }
162                             if (e instanceof ClassPrepareEvent) {
163                                 tref = ((ClassPrepareEvent) e).thread();
164                             }
165                             if (e instanceof ThreadStartEvent) {
166                                 tref = ((ThreadStartEvent) e).thread();
167                             }
168                             if (e instanceof ThreadDeathEvent) {
169                                 tref = ((ThreadDeathEvent) e).thread();
170                             }
171                          }
172                          if (tref != null) {
173                             suspendedThread = ((JPDAThreadImpl) debugger.getThread(tref));
174                             suspendedThread.notifySuspended();
175                          }
176                      }
177                      if (logger.isLoggable(Level.FINE)) {
178                          switch (suspendPolicy) {
179                              case EventRequest.SUSPEND_ALL:
180                                  logger.fine("JDI new events (suspend all)=============================================");
181                                  break;
182                              case EventRequest.SUSPEND_EVENT_THREAD:
183                                  logger.fine("JDI new events (suspend one)=============================================");
184                                  break;
185                              case EventRequest.SUSPEND_NONE:
186                                  logger.fine("JDI new events (suspend none)=============================================");
187                                  break;
188                              default:
189                                  logger.fine("JDI new events (?????)=============================================");
190                                  break;
191                          }
192                      }
193                      EventIterator i = eventSet.eventIterator ();
194                      while (i.hasNext ()) {
195                          Event e = i.nextEvent ();
196                          if ((e instanceof VMDeathEvent) ||
197                                  (e instanceof VMDisconnectEvent)
198                             ) {
199
200                              if (logger.isLoggable(Level.FINE)) {
201                                  printEvent (e, null);
202                              }
203                              synchronized (Operator.this) {
204                                  stop = true;
205                              }
206 // disconnected = true;
207
if (finalizer != null) finalizer.run ();
208                              //S ystem.out.println ("EVENT: " + e); // NOI18N
209
//S ystem.out.println ("Operator end2"); // NOI18N
210
finalizer = null;
211                              eventQueue = null;
212                              starter = null;
213                              return;
214                          }
215                          
216                          if ((e instanceof VMStartEvent) && (starter != null)) {
217                              resume = resume & starter.exec (e);
218                              //S ystem.out.println ("Operator.start VM"); // NOI18N
219
if (logger.isLoggable(Level.FINE)) {
220                                  printEvent (e, null);
221                              }
222                              continue;
223                          }
224                          Executor exec = null;
225                          if (e.request () == null) {
226                              if (logger.isLoggable(Level.FINE)) {
227                                  logger.fine("EVENT: " + e + " REQUEST: null"); // NOI18N
228
}
229                          } else
230                              exec = (Executor) e.request ().getProperty ("executor");
231
232                          if (logger.isLoggable(Level.FINE)) {
233                              printEvent (e, exec);
234                          }
235
236                          // safe invocation of user action
237
if (exec != null)
238                              try {
239                                  startEventOnly = false;
240                                  resume = resume & exec.exec (e);
241                              } catch (VMDisconnectedException exc) {
242 // disconnected = true;
243
synchronized (Operator.this) {
244                                      stop = true;
245                                  }
246                                  if (finalizer != null) finalizer.run ();
247                                  //S ystem.out.println ("EVENT: " + e); // NOI18N
248
//S ystem.out.println ("Operator end"); // NOI18N
249
return;
250                              } catch (Exception JavaDoc ex) {
251                                  ErrorManager.getDefault().notify(ex);
252                              }
253                      } // while
254
// S ystem.out.println ("END (" + set.suspendPolicy () + ") ==========================================================================="); // NOI18N
255
if (logger.isLoggable(Level.FINE)) {
256                          logger.fine("JDI events dispatched (resume " + (resume && (!startEventOnly)) + ")");
257                          logger.fine(" resume = "+resume+", startEventOnly = "+startEventOnly);
258                      }
259                      if (resume && (!startEventOnly)) {
260                          if (suspendedAll) {
261                              //TODO: Not really all can be suspended!
262
debugger.notifyToBeResumedAll();
263                          }
264                          if (suspendedThread != null) {
265                              suspendedThread.notifyToBeResumed();
266                          }
267                          synchronized (resumeLock) {
268                             eventSet.resume ();
269                          }
270                      }
271                      if (!resume) { // Check for multiply-suspended threads
272
synchronized (resumeLock) {
273                              List JavaDoc<ThreadReference> threads = eventSet.virtualMachine().allThreads();
274                              for (ThreadReference t : threads) {
275                                  while (t.suspendCount() > 1) t.resume();
276                              }
277                          }
278                      }
279                  }// for
280
} catch (VMDisconnectedException e) {
281              //} catch (InterruptedException e) {
282
} catch (Exception JavaDoc e) {
283                  ErrorManager.getDefault().notify(e);
284              }
285              if (finalizer != null) finalizer.run ();
286              //S ystem.out.println ("Operator end"); // NOI18N
287
finalizer = null;
288              eventQueue = null;
289              starter = null;
290          }
291      }, "Debugger operator thread"); // NOI18N
292
}
293
294     /**
295     * Starts checking of JPDA messages.
296     */

297     public void start () {
298         thread.start ();
299     }
300
301     /**
302      * Binds the specified object with the event request.
303      * If the request is already bound with another object,
304      * the old binding is removed.
305      *
306      * @param req request
307      * @param e object to be bound with the request
308      * (if <TT>null</TT>, the binding is removed - the same as <TT>unregister()</TT>)
309      * @see #unregister
310      */

311     public synchronized void register (EventRequest req, Executor e) {
312         req.putProperty ("executor", e); // NOI18N
313
if (staledEvents.size() > 0 && req instanceof StepRequest) {
314             boolean addAsStaled = false;
315             for (Iterator JavaDoc<EventSet> it = staledEvents.iterator(); it.hasNext(); ) {
316                 EventSet evSet = it.next();
317                 for (Iterator JavaDoc<Event> itSet = evSet.iterator(); itSet.hasNext(); ) {
318                     Event ev = itSet.next();
319                     EventRequest evReq = ev.request();
320                     if (!(evReq instanceof StepRequest)) {
321                         addAsStaled = true;
322                         break;
323                     } else {
324                         ThreadReference evThread = ((StepRequest) evReq).thread();
325                         ThreadReference reqThread = ((StepRequest) req).thread();
326                         if (reqThread.equals(evThread)) {
327                             addAsStaled = true;
328                             break;
329                         }
330                     }
331                 }
332                 if (addAsStaled) break;
333             }
334             // Will be added if there is not a staled step event or if all staled
335
// step events are on different threads.
336
if (addAsStaled) {
337                 staledRequests.add(req);
338             }
339         };
340     }
341
342     /**
343      * Removes binding between the specified event request and a registered object.
344      *
345      * @param req request
346      * @see #register
347      */

348     public synchronized void unregister (EventRequest req) {
349         req.putProperty ("executor", null); // NOI18N
350
staledRequests.remove(req);
351     }
352     
353     /**
354      * Stop the operator thread.
355      */

356     public void stop() {
357         synchronized (this) {
358             staledRequests.clear();
359             staledEvents.clear();
360             if (stop) return ; // Do not interrupt the thread when we're stopped
361
stop = true;
362         }
363         thread.interrupt();
364     }
365     
366     /**
367      * Notifies that breakpoints were disabled and therefore no breakpoint events should occur
368      * until {@link #breakpointsEnabled} is called.
369      */

370     public synchronized void breakpointsDisabled() {
371         breakpointsDisabled = true;
372     }
373     
374     /**
375      * Notifies that breakpoints were enabled again and therefore breakpoint events can occur.
376      */

377     public synchronized void breakpointsEnabled() {
378         breakpointsDisabled = false;
379     }
380     
381     public boolean flushStaledEvents() {
382         boolean areStaledEvents;
383         synchronized (this) {
384             areStaledEvents = staledEvents.size() > 0;
385             if (areStaledEvents) {
386                 thread.interrupt();
387             }
388         }
389         return areStaledEvents;
390     }
391
392     private void printEvent (Event e, Executor exec) {
393         try {
394             if (e instanceof ClassPrepareEvent) {
395                 logger.fine("JDI EVENT: ClassPrepareEvent " + ((ClassPrepareEvent) e).referenceType ()); // NOI18N
396
} else
397             if (e instanceof ClassUnloadEvent) {
398                 logger.fine("JDI EVENT: ClassUnloadEvent " + ((ClassUnloadEvent) e).className ()); // NOI18N
399
} else
400             if (e instanceof ThreadStartEvent) {
401                 try {
402                     logger.fine("JDI EVENT: ThreadStartEvent " + ((ThreadStartEvent) e).thread ()); // NOI18N
403
} catch (Exception JavaDoc ex) {
404                     logger.fine("JDI EVENT: ThreadStartEvent1 " + e); // NOI18N
405
}
406             } else
407             if (e instanceof ThreadDeathEvent) {
408                 try {
409                     logger.fine("JDI EVENT: ThreadDeathEvent " + ((ThreadDeathEvent) e).thread ()); // NOI18N
410
} catch (Exception JavaDoc ex) {
411                     logger.fine("JDI EVENT: ThreadDeathEvent1 " + e); // NOI18N
412
}
413             } else
414             if (e instanceof MethodEntryEvent) {
415                 try {
416                     logger.fine("JDI EVENT: MethodEntryEvent " + e);
417                 } catch (Exception JavaDoc ex) {
418                     logger.fine("JDI EVENT: MethodEntryEvent " + e);
419                 }
420             } else
421             if (e instanceof BreakpointEvent) {
422                 logger.fine("JDI EVENT: BreakpointEvent " + ((BreakpointEvent) e).thread () + " : " + ((BreakpointEvent) e).location ()); // NOI18N
423
} else
424             if (e instanceof StepEvent) {
425                 logger.fine("JDI EVENT: StepEvent " + ((StepEvent) e).thread () + " : " + ((StepEvent) e).location ()); // NOI18N
426
} else
427                 logger.fine("JDI EVENT: " + e + " : " + exec); // NOI18N
428
} catch (Exception JavaDoc ex) {
429         }
430     }
431 }
432
Popular Tags