1 /* 2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * This source code is provided to illustrate the usage of a given feature 28 * or technique and has been deliberately simplified. Additional steps 29 * required for a production-quality application, such as security checks, 30 * input validation and proper error handling, might not be present in 31 * this sample code. 32 */ 33 34 35 package com.sun.tools.example.debug.bdi; 36 37 import com.sun.jdi.*; 38 import com.sun.jdi.event.*; 39 40 import com.sun.tools.example.debug.event.*; 41 42 import javax.swing.SwingUtilities; 43 44 /** 45 */ 46 class JDIEventSource extends Thread { 47 48 private /*final*/ EventQueue queue; 49 private /*final*/ Session session; 50 private /*final*/ ExecutionManager runtime; 51 private final JDIListener firstListener = new FirstListener(); 52 53 private boolean wantInterrupt; //### Hack 54 55 /** 56 * Create event source. 57 */ 58 JDIEventSource(Session session) { 59 super("JDI Event Set Dispatcher"); 60 this.session = session; 61 this.runtime = session.runtime; 62 this.queue = session.vm.eventQueue(); 63 } 64 65 @Override 66 public void run() { 67 try { 68 runLoop(); 69 } catch (Exception exc) { 70 //### Do something different for InterruptedException??? 71 // just exit 72 } 73 session.running = false; 74 } 75 76 private void runLoop() throws InterruptedException { 77 AbstractEventSet es; 78 do { 79 EventSet jdiEventSet = queue.remove(); 80 es = AbstractEventSet.toSpecificEventSet(jdiEventSet); 81 session.interrupted = es.suspendedAll(); 82 dispatchEventSet(es); 83 } while(!(es instanceof VMDisconnectEventSet)); 84 } 85 86 //### Gross foul hackery! 87 private void dispatchEventSet(final AbstractEventSet es) { 88 SwingUtilities.invokeLater(new Runnable() { 89 @Override 90 public void run() { 91 boolean interrupted = es.suspendedAll(); 92 es.notify(firstListener); 93 boolean wantInterrupt = JDIEventSource.this.wantInterrupt; 94 for (JDIListener jl : session.runtime.jdiListeners) { 95 es.notify(jl); 96 } 97 if (interrupted && !wantInterrupt) { 98 session.interrupted = false; 99 //### Catch here is a hack 100 try { 101 session.vm.resume(); 102 } catch (VMDisconnectedException ee) {} 103 } 104 if (es instanceof ThreadDeathEventSet) { 105 ThreadReference t = ((ThreadDeathEventSet)es).getThread(); 106 session.runtime.removeThreadInfo(t); 107 } 108 } 109 }); 110 } 111 112 private void finalizeEventSet(AbstractEventSet es) { 113 if (session.interrupted && !wantInterrupt) { 114 session.interrupted = false; 115 //### Catch here is a hack 116 try { 117 session.vm.resume(); 118 } catch (VMDisconnectedException ee) {} 119 } 120 if (es instanceof ThreadDeathEventSet) { 121 ThreadReference t = ((ThreadDeathEventSet)es).getThread(); 122 session.runtime.removeThreadInfo(t); 123 } 124 } 125 126 //### This is a Hack, deal with it 127 private class FirstListener implements JDIListener { 128 129 @Override 130 public void accessWatchpoint(AccessWatchpointEventSet e) { 131 session.runtime.validateThreadInfo(); 132 wantInterrupt = true; 133 } 134 135 @Override 136 public void classPrepare(ClassPrepareEventSet e) { 137 wantInterrupt = false; 138 runtime.resolve(e.getReferenceType()); 139 } 140 141 @Override 142 public void classUnload(ClassUnloadEventSet e) { 143 wantInterrupt = false; 144 } 145 146 @Override 147 public void exception(ExceptionEventSet e) { 148 wantInterrupt = true; 149 } 150 151 @Override 152 public void locationTrigger(LocationTriggerEventSet e) { 153 session.runtime.validateThreadInfo(); 154 wantInterrupt = true; 155 } 156 157 @Override 158 public void modificationWatchpoint(ModificationWatchpointEventSet e) { 159 session.runtime.validateThreadInfo(); 160 wantInterrupt = true; 161 } 162 163 @Override 164 public void threadDeath(ThreadDeathEventSet e) { 165 wantInterrupt = false; 166 } 167 168 @Override 169 public void threadStart(ThreadStartEventSet e) { 170 wantInterrupt = false; 171 } 172 173 @Override 174 public void vmDeath(VMDeathEventSet e) { 175 //### Should have some way to notify user 176 //### that VM died before the session ended. 177 wantInterrupt = false; 178 } 179 180 @Override 181 public void vmDisconnect(VMDisconnectEventSet e) { 182 //### Notify user? 183 wantInterrupt = false; 184 session.runtime.endSession(); 185 } 186 187 @Override 188 public void vmStart(VMStartEventSet e) { 189 //### Do we need to do anything with it? 190 wantInterrupt = false; 191 } 192 } 193 }