001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.model.debug;
038:
039: import edu.rice.cs.drjava.model.EventNotifier;
040: import edu.rice.cs.drjava.model.OpenDefinitionsDocument;
041:
042: import java.awt.EventQueue;
043:
044: /** Keeps track of all listeners to a Debugger, and has the ability to notify them of some event.
045: * <p>
046: * This class has a specific role of managing DebugListeners. Other classes with similar names use similar code to
047: * perform the same function for other interfaces, e.g. InteractionsEventNotifier and GlobalEventNotifier. These
048: * classes implement the appropriate interface definition so that they can be used transparently as composite packaging
049: * for a particular listener interface.
050: * <p>
051: * Components which might otherwise manage their own list of listeners use EventNotifiers instead to simplify their
052: * internal implementation. Notifiers should therefore be considered a private implementation detail of the
053: * components, and should not be used directly outside of the "host" component.
054: * <p>
055: * All methods in this class must use the synchronization methods provided by ReaderWriterLock. This ensures that
056: * multiple notifications (reads) can occur simultaneously, but only one thread can be adding or removing listeners
057: * (writing) at a time, and no reads can occur during a write.
058: * <p>
059: * <i>No</i> methods on this class should be synchronized using traditional Java synchronization!
060: * <p>
061: *
062: * @version $Id: DebugEventNotifier.java 4255 2007-08-28 19:17:37Z mgricken $
063: */
064: public class DebugEventNotifier extends EventNotifier<DebugListener>
065: implements DebugListener {
066:
067: /** Called when debugger mode has been enabled. Must be executed in event thread. */
068: public void debuggerStarted() {
069: assert EventQueue.isDispatchThread();
070: _lock.startRead();
071: try {
072: int size = _listeners.size();
073: for (int i = 0; i < size; i++) {
074: _listeners.get(i).debuggerStarted();
075: }
076: } finally {
077: _lock.endRead();
078: }
079: }
080:
081: /** Called when debugger mode has been disabled. Must be executed in event thread. */
082: public void debuggerShutdown() {
083: assert EventQueue.isDispatchThread();
084: _lock.startRead();
085: try {
086: int size = _listeners.size();
087: for (int i = 0; i < size; i++) {
088: _listeners.get(i).debuggerShutdown();
089: }
090: } finally {
091: _lock.endRead();
092: }
093: }
094:
095: /** Called when the given line is reached by the current thread in the debugger, to request that the line be
096: * displayed. Must be executed only in the event thread.
097: * @param doc Document to display
098: * @param lineNumber Line to display or highlight
099: * @param shouldHighlight true iff the line should be highlighted.
100: */
101: public void threadLocationUpdated(OpenDefinitionsDocument doc,
102: int lineNumber, boolean shouldHighlight) {
103: assert EventQueue.isDispatchThread();
104: _lock.startRead();
105: try {
106: int size = _listeners.size();
107: for (int i = 0; i < size; i++) {
108: _listeners.get(i).threadLocationUpdated(doc,
109: lineNumber, shouldHighlight);
110: }
111: } finally {
112: _lock.endRead();
113: }
114: }
115:
116: /** Called when a breakpoint is set in a document. Must be executed in event thread.
117: * @param bp the breakpoint
118: * @param index the index at which it was added
119: */
120: public void regionAdded(Breakpoint bp, int index) {
121: assert EventQueue.isDispatchThread();
122: _lock.startRead();
123: try {
124: int size = _listeners.size();
125: for (int i = 0; i < size; i++) {
126: _listeners.get(i).regionAdded(bp, index);
127: }
128: } finally {
129: _lock.endRead();
130: }
131: }
132:
133: /** Called when a breakpoint is reached during execution. Must be executed in event thread.
134: * @param bp the breakpoint
135: */
136: public void breakpointReached(Breakpoint bp) {
137: assert EventQueue.isDispatchThread();
138: _lock.startRead();
139: try {
140: int size = _listeners.size();
141: for (int i = 0; i < size; i++) {
142: _listeners.get(i).breakpointReached(bp);
143: }
144: } finally {
145: _lock.endRead();
146: }
147: }
148:
149: /** Called when a breakpoint is changed during execution. Must be executed in event thread.
150: * @param bp the breakpoint
151: * @param index the index at which it was changed
152: */
153: public void regionChanged(Breakpoint bp, int index) {
154: assert EventQueue.isDispatchThread();
155: _lock.startRead();
156: try {
157: int size = _listeners.size();
158: for (int i = 0; i < size; i++) {
159: _listeners.get(i).regionChanged(bp, index);
160: }
161: } finally {
162: _lock.endRead();
163: }
164: }
165:
166: /** Called when a watch is set. Must be executed in event thread.
167: * @param w the watch
168: */
169: public void watchSet(DebugWatchData w) {
170: assert EventQueue.isDispatchThread();
171: _lock.startRead();
172: try {
173: int size = _listeners.size();
174: for (int i = 0; i < size; i++) {
175: _listeners.get(i).watchSet(w);
176: }
177: } finally {
178: _lock.endRead();
179: }
180: }
181:
182: /** Called when a watch is removed. Must be executed in event thread.
183: * @param w the watch
184: */
185: public void watchRemoved(DebugWatchData w) {
186: assert EventQueue.isDispatchThread();
187: _lock.startRead();
188: try {
189: int size = _listeners.size();
190: for (int i = 0; i < size; i++) {
191: _listeners.get(i).watchRemoved(w);
192: }
193: } finally {
194: _lock.endRead();
195: }
196: }
197:
198: /** Called when a breakpoint is removed from a document. Must be executed in event thread.
199: * @param bp the breakpoint
200: */
201: public void regionRemoved(Breakpoint bp) {
202: assert EventQueue.isDispatchThread();
203: _lock.startRead();
204: try {
205: int size = _listeners.size();
206: for (int i = 0; i < size; i++)
207: _listeners.get(i).regionRemoved(bp);
208: } finally {
209: _lock.endRead();
210: }
211: }
212:
213: /** Called when a step is requested on the current thread. Must be executed in event thread. */
214: public void stepRequested() {
215: assert EventQueue.isDispatchThread();
216: _lock.startRead();
217: try {
218: int size = _listeners.size();
219: for (int i = 0; i < size; i++)
220: _listeners.get(i).stepRequested();
221: } finally {
222: _lock.endRead();
223: }
224: }
225:
226: /** Called when the current thread is suspended. */
227: public void currThreadSuspended() {
228: _lock.startRead();
229: try {
230: int size = _listeners.size();
231: for (int i = 0; i < size; i++)
232: _listeners.get(i).currThreadSuspended();
233: } finally {
234: _lock.endRead();
235: }
236: }
237:
238: /** Called when the current thread is resumed. Must be executed in event thread. */
239: public void currThreadResumed() {
240: assert EventQueue.isDispatchThread();
241: _lock.startRead();
242: try {
243: int size = _listeners.size();
244: for (int i = 0; i < size; i++)
245: _listeners.get(i).currThreadResumed();
246: } finally {
247: _lock.endRead();
248: }
249: }
250:
251: /** Called when a thread starts. Must be executed in event thread. */
252: public void threadStarted() {
253: assert EventQueue.isDispatchThread();
254: _lock.startRead();
255: try {
256: int size = _listeners.size();
257: for (int i = 0; i < size; i++)
258: _listeners.get(i).threadStarted();
259: } finally {
260: _lock.endRead();
261: }
262: }
263:
264: /** Called when the current thread dies. Must be executed in event thread. */
265: public void currThreadDied() {
266: assert EventQueue.isDispatchThread();
267: _lock.startRead();
268: try {
269: int size = _listeners.size();
270: for (int i = 0; i < size; i++)
271: _listeners.get(i).currThreadDied();
272: } finally {
273: _lock.endRead();
274: }
275: }
276:
277: /** Called when any thread other than the current thread dies. Must be executed in event thread. */
278: public void nonCurrThreadDied() {
279: assert EventQueue.isDispatchThread();
280: _lock.startRead();
281: try {
282: int size = _listeners.size();
283: for (int i = 0; i < size; i++)
284: _listeners.get(i).nonCurrThreadDied();
285: } finally {
286: _lock.endRead();
287: }
288: }
289:
290: /** Called when the current (selected) thread is set in the debugger.
291: * @param thread the thread that was set as current
292: */
293: public void currThreadSet(DebugThreadData thread) {
294: _lock.startRead();
295: try {
296: int size = _listeners.size();
297: for (int i = 0; i < size; i++) {
298: _listeners.get(i).currThreadSet(thread);
299: }
300: } finally {
301: _lock.endRead();
302: }
303: }
304: }
|