KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > model > GlobalEventNotifier


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32 END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.drjava.model;
35
36 import java.io.File JavaDoc;
37 import java.io.Serializable JavaDoc;
38 import java.util.List JavaDoc;
39
40 import edu.rice.cs.drjava.model.compiler.CompilerListener;
41 import edu.rice.cs.util.FileOpenSelector;
42 import edu.rice.cs.util.classloader.ClassFileError;
43 import edu.rice.cs.util.swing.AsyncTask;
44
45 /** Keeps track of all listeners to the model, and has the ability to notify them of some event.
46  * <p>
47  * This class has a specific role of managing GlobalModelListeners. Other classes with similar names use similar
48  * code to perform the same function for other interfaces, e.g. InteractionsEventNotifier and JavadocEventNotifier.
49  * These classes implement the appropriate interface definition so that they can be used transparently as composite
50  * packaging for a particular listener interface.
51  * <p>
52  * Components which might otherwise manage their own list of listeners use EventNotifiers instead to simplify their
53  * internal implementation. Notifiers should therefore be considered a private implementation detail of the
54  * components, and should not be used directly outside of the "host" component.
55  * <p>
56  * TODO: remove direct references to GlobalEventNotifier outside of DefaultGlobalModel
57  * TODO: remove public modifier from this class when above has happened
58  *
59  * All methods in this class must use the synchronization methods provided by ReaderWriterLock. This ensures that
60  * multiple notifications (reads) can occur simultaneously, but only one thread can be adding or removing listeners
61  * (writing) at a time, and no reads can occur during a write.
62  * <p>
63  * <i>No</i> methods on this class should be synchronized using traditional Java synchronization!
64  * <p>
65  * @version $Id: GlobalEventNotifier.java 4076 2007-01-19 23:01:04Z dlsmith $
66  */

67 public class GlobalEventNotifier extends EventNotifier<GlobalModelListener>
68     implements GlobalModelListener, Serializable JavaDoc {
69
70  public <P,R> void executeAsyncTask(AsyncTask<P,R> task, P param, boolean showProgress, boolean lockUI) {
71     _lock.startRead();
72     try { for (GlobalModelListener l : _listeners) { l.executeAsyncTask(task, param, showProgress, lockUI); } }
73     finally { _lock.endRead(); }
74   }
75   
76   public void fileNotFound(File JavaDoc f) {
77     _lock.startRead();
78     try { for (GlobalModelListener l : _listeners) { l.fileNotFound(f); } }
79     finally { _lock.endRead(); }
80   }
81   
82   /**
83    * Performs any UI related steps to handle the case in which a file is being opened that
84    * is already open and modified. The two choices are to revert to the copy on disk, or to
85    * keep the current changes.
86    * @param doc {@code true} if the user wishes to revert the document, {@code false} to ignore
87    */

88   public void handleAlreadyOpenDocument(OpenDefinitionsDocument doc) {
89     _lock.startRead();
90     try { for(GlobalModelListener l : _listeners) { l.handleAlreadyOpenDocument(doc); } }
91     finally { _lock.endRead(); }
92   }
93   
94   /* -------------- project state ------------------*/
95   public void projectOpened(File JavaDoc pfile, FileOpenSelector files) {
96     _lock.startRead();
97     try { for (GlobalModelListener l : _listeners) { l.projectOpened(pfile, files); } }
98     finally { _lock.endRead(); }
99   }
100   
101   public void projectClosed() {
102     _lock.startRead();
103     try { for (GlobalModelListener l : _listeners) { l.projectClosed();} }
104     finally { _lock.endRead(); }
105   }
106   
107   public void projectModified() {
108     _lock.startRead();
109     try { for (GlobalModelListener l : _listeners) { l.projectModified(); } }
110     finally { _lock.endRead(); }
111   }
112   
113   public void projectBuildDirChanged() {
114     _lock.startRead();
115     try { for (GlobalModelListener l : _listeners) { l.projectBuildDirChanged(); } }
116     finally { _lock.endRead(); }
117   }
118   
119   public void projectWorkDirChanged() {
120     _lock.startRead();
121     try { for (GlobalModelListener l : _listeners) { l.projectWorkDirChanged(); } }
122     finally { _lock.endRead(); }
123   }
124   
125   public void projectRunnableChanged() {
126     _lock.startRead();
127     try { for (GlobalModelListener l : _listeners) { l.projectRunnableChanged(); } }
128     finally { _lock.endRead(); }
129   }
130   
131   
132   /* ---------- Deprecated Methods ---------- */
133
134   /** Lets the listeners know some event has taken place.
135    * @param n tells the listener what happened.
136    */

137   public void notifyListeners(Notifier n) {
138     _lock.startRead();
139     try { for (GlobalModelListener l : _listeners) { n.notifyListener(l); } }
140     finally { _lock.endRead(); }
141   }
142
143   /** Allows the GlobalModel to ask its listeners a yes/no question and receive a response.
144    * @param p the question being asked of the listeners
145    * @return the listeners' responses ANDed together, true if they all
146    * agree, false if some disagree
147    * @deprecated Use listener methods directly instead.
148    */

149   @Deprecated JavaDoc
150   public boolean pollListeners(Poller p) {
151     _lock.startRead();
152     try {
153       for (GlobalModelListener l: _listeners) { if (! p.poll(l)) return false; }
154       return true;
155     }
156     finally { _lock.endRead(); }
157   }
158
159   /**
160    * Class model for notifying listeners of an event.
161    * @deprecated Use listener methods directly instead.
162    */

163   @Deprecated JavaDoc
164   public abstract static class Notifier {
165     public abstract void notifyListener(GlobalModelListener l);
166   }
167
168   /**
169    * Class model for asking listeners a yes/no question.
170    * @deprecated Use listener methods directly instead.
171    */

172   @Deprecated JavaDoc
173   public abstract static class Poller {
174     public abstract boolean poll(GlobalModelListener l);
175   }
176
177   // ---------- End of Deprecated Methods ----------
178

179
180
181   //------------------------------ GlobalModel -------------------------------//
182

183   /** Called when a file's main method is about to be run. */
184   public void runStarted(OpenDefinitionsDocument doc) {
185     _lock.startRead();
186     try { for (GlobalModelListener l : _listeners) { l.runStarted(doc); } }
187     finally { _lock.endRead(); }
188   }
189
190   /** Called after a new document is created. */
191   public void newFileCreated(OpenDefinitionsDocument doc) {
192     _lock.startRead();
193     try { for (GlobalModelListener l : _listeners) { l.newFileCreated(doc); } }
194     finally { _lock.endRead(); }
195   }
196
197   /** Called when the console window is reset. */
198   public void consoleReset() {
199     _lock.startRead();
200     try { for (GlobalModelListener l : _listeners) { l.consoleReset(); } }
201     finally { _lock.endRead(); }
202   }
203
204   /** Called after the current document is saved. */
205   public void fileSaved(OpenDefinitionsDocument doc) {
206 // ScrollableDialog sd = new ScrollableDialog(null, "fileSaved(" + doc + ") called in GlobalEventNotifier.java", "", "");
207
// sd.show();
208
_lock.startRead();
209     try { for (GlobalModelListener l : _listeners) { l.fileSaved(doc); } }
210     finally { _lock.endRead(); }
211   }
212
213   /** Called after a file is opened and read into the current document. */
214   public void fileOpened(OpenDefinitionsDocument doc) {
215     _lock.startRead();
216     try { for (GlobalModelListener l : _listeners) { l.fileOpened(doc); } }
217     finally { _lock.endRead(); }
218   }
219
220   /** Called after a document is closed. */
221   public void fileClosed(OpenDefinitionsDocument doc) {
222     _lock.startRead();
223     try { for (GlobalModelListener l : _listeners) { l.fileClosed(doc); } }
224     finally { _lock.endRead(); }
225   }
226
227   /** Called after a document is reverted. */
228   public void fileReverted(OpenDefinitionsDocument doc) {
229     _lock.startRead();
230     try { for (GlobalModelListener l : _listeners) { l.fileReverted(doc); } }
231     finally { _lock.endRead(); }
232   }
233
234   /** Called when an undoable edit occurs. */
235   public void undoableEditHappened() {
236     _lock.startRead();
237     try { for (GlobalModelListener l : _listeners) { l.undoableEditHappened(); } }
238     finally { _lock.endRead(); }
239   }
240
241   /** Called to ask the listeners if it is OK to abandon the current document. */
242   public boolean canAbandonFile(OpenDefinitionsDocument doc) {
243     _lock.startRead();
244     try {
245       for (GlobalModelListener l: _listeners) { if (! l.canAbandonFile(doc)) return false; }
246       return true;
247     }
248     finally { _lock.endRead(); }
249   }
250
251    /** Called to ask the listeners save the file before quitting at the user's option.
252     * @return true if quitting should continue, false if the user cancelled */

253   public boolean quitFile(OpenDefinitionsDocument doc) {
254     _lock.startRead();
255     try {
256       // if one of the listeners returns false (=user cancelled), abort
257
for (GlobalModelListener l: _listeners) { if (!l.quitFile(doc)) return false; }
258     }
259     finally { _lock.endRead(); }
260     return true;
261   }
262
263   /** Called to ask the listeners if it is OK to revert the current document to the version saved on disk. */
264   public boolean shouldRevertFile(OpenDefinitionsDocument doc) {
265     _lock.startRead();
266     try {
267       for (GlobalModelListener l: _listeners) { if (! l.shouldRevertFile(doc)) return false; }
268       return true;
269     }
270     finally { _lock.endRead(); }
271   }
272
273   /** Called when the selection in the navigator changes the current directory without changing the active document. */
274   public void currentDirectoryChanged(File JavaDoc dir) {
275     _lock.startRead();
276     try { for (GlobalModelListener l : _listeners) { l.currentDirectoryChanged(dir); } }
277     finally { _lock.endRead(); }
278   }
279   
280   /** Called when the selection in the navigator changes the active document. */
281   public void activeDocumentChanged(OpenDefinitionsDocument active) {
282     _lock.startRead();
283     try { for (GlobalModelListener l : _listeners) { l.activeDocumentChanged(active); } }
284     finally { _lock.endRead(); }
285   }
286   
287    /** Called to shift the focus to the Definitions Pane. */
288   public void focusOnDefinitionsPane() {
289     _lock.startRead();
290     try { for (GlobalModelListener l : _listeners) { l.focusOnDefinitionsPane(); } }
291     finally { _lock.endRead(); }
292   }
293 // /** Called to demand that all files be saved before running the main method of a document. It is up to the caller
294
// * of this method to check if the documents have been saved, using IGetDocuments.hasModifiedDocuments(). This is
295
// * nor used currently, but it is commented out in case it is needed later. */
296
// public void saveBeforeRun() {
297
// _lock.startRead();
298
// try { for (GlobalModelListener l : _listeners) { l.saveBeforeRun(); } }
299
// finally { _lock.endRead(); }
300
// }
301

302   //------------------------------ Interactions ------------------------------//
303

304   /** Called after an interaction is started by the GlobalModel. */
305   public void interactionStarted() {
306     _lock.startRead();
307     try { for (GlobalModelListener l : _listeners) { l.interactionStarted(); } }
308     finally { _lock.endRead(); }
309   }
310
311   /** Called when an interaction has finished running. */
312   public void interactionEnded() {
313     _lock.startRead();
314     try { for (GlobalModelListener l : _listeners) { l.interactionEnded(); } }
315     finally { _lock.endRead(); }
316   }
317
318   /** Called when the interactions window generates a syntax error.
319    * @param offset the error's offset into the InteractionsDocument.
320    * @param length the length of the error.
321    */

322   public void interactionErrorOccurred(int offset, int length) {
323     _lock.startRead();
324     try { for (GlobalModelListener l : _listeners) { l.interactionErrorOccurred(offset, length); } }
325     finally { _lock.endRead(); }
326   }
327
328   /** Called when the interactionsJVM has begun resetting. */
329   public void interpreterResetting() {
330     _lock.startRead();
331     try { for (GlobalModelListener l : _listeners) { l.interpreterResetting(); } }
332     finally { _lock.endRead(); }
333   }
334
335   /** Called when the interactions window is reset. */
336   public void interpreterReady(File JavaDoc wd) {
337     _lock.startRead();
338     try { for (GlobalModelListener l : _listeners) { l.interpreterReady(wd); } }
339     finally { _lock.endRead(); }
340   }
341
342   /** Called if the interpreter reset failed.
343    * @param t Throwable explaining why the reset failed.
344    * (Subclasses must maintain listeners.)
345    */

346   public void interpreterResetFailed(final Throwable JavaDoc t) {
347     _lock.startRead();
348     try { for (GlobalModelListener l : _listeners) { l.interpreterResetFailed(t); } }
349     finally { _lock.endRead(); }
350   }
351
352   /** Called when the interactions JVM was closed by System.exit or by being aborted. Immediately after this the
353    * interactions will be reset.
354    * @param status the exit code
355    */

356   public void interpreterExited(int status) {
357     _lock.startRead();
358     try { for (GlobalModelListener l : _listeners) { l.interpreterExited(status); } }
359     finally { _lock.endRead(); }
360   }
361
362   /** Called when the active interpreter is changed.
363    * @param inProgress Whether the new interpreter is processing an interaction (i.e,. whether an interactionEnded
364    * event will be fired)
365    */

366   public void interpreterChanged(boolean inProgress) {
367     _lock.startRead();
368     try { for (GlobalModelListener l : _listeners) { l.interpreterChanged(inProgress); } }
369     finally { _lock.endRead(); }
370   }
371
372   //-------------------------------- Compiler --------------------------------//
373

374   /** Called after a compile is started by the GlobalModel. */
375   public void compileStarted() {
376     _lock.startRead();
377     try { for (GlobalModelListener l : _listeners) { l.compileStarted(); }
378     }
379     finally { _lock.endRead(); }
380   }
381
382   /** Called when a compile has finished running. */
383   public void compileEnded(File JavaDoc workDir, List JavaDoc<? extends File JavaDoc> excludedFiles) {
384     _lock.startRead();
385     try { for (GlobalModelListener l : _listeners) { l.compileEnded(workDir, excludedFiles); } }
386     finally { _lock.endRead(); }
387   }
388
389   /** Called to demand that all files be saved before compiling. It is up to the caller of this method to check
390    * if the documents have been saved, using IGetDocuments.hasModifiedDocuments().
391    */

392   public void saveBeforeCompile() {
393     _lock.startRead();
394     try { for (GlobalModelListener l : _listeners) { l.saveBeforeCompile(); } }
395     finally { _lock.endRead(); }
396   }
397
398   /** Called to demand that the active document, which is untitled, is saved before compiling. */
399   public void saveUntitled() {
400     _lock.startRead();
401     try { for (GlobalModelListener l : _listeners) { l.saveUntitled(); } }
402     finally { _lock.endRead(); }
403   }
404   
405   //---------------------------------- JUnit ---------------------------------//
406

407   /** Called when trying to test a non-TestCase class.
408    * @param isTestAll whether or not it was a use of the test all button
409    */

410   public void nonTestCase(boolean isTestAll) {
411     _lock.startRead();
412     try { for (GlobalModelListener l : _listeners) { l.nonTestCase(isTestAll); } }
413     finally { _lock.endRead(); }
414   }
415
416   /** Called when trying to test an illegal class file.
417    * @param e the ClassFileError thrown when DrJava attempted to load the offending file
418    */

419   public void classFileError(ClassFileError e) {
420     _lock.startRead();
421     try { for (GlobalModelListener l : _listeners) { l.classFileError(e); } }
422     finally { _lock.endRead(); }
423   }
424   
425   /** Called before attempting unit testing if tested class files are out of sync, to give the user a chance to save. Do
426    * not continue with JUnit if the user doesn't recompile!
427    */

428   public void compileBeforeJUnit(final CompilerListener cl) {
429 // Utilities.show("compileBeforeJUnit invoked with argument " + cl + " in GlobalEventNotifier " + this);
430
_lock.startRead();
431     try { for (GlobalModelListener l : _listeners) { l.compileBeforeJUnit(cl); } }
432     finally { _lock.endRead(); }
433   }
434   
435   /** Called after JUnit is started by the GlobalModel. */
436   public void junitStarted() {
437     _lock.startRead();
438     try { for (GlobalModelListener l : _listeners) { l.junitStarted(); } }
439     finally { _lock.endRead(); }
440   }
441
442   /** Called when testing specific list of classes. */
443   public void junitClassesStarted() {
444     _lock.startRead();
445     try { for (GlobalModelListener l : _listeners) { l.junitClassesStarted(); } }
446     finally { _lock.endRead(); }
447   }
448   
449   /** Called to indicate that a suite of tests has started running.
450    * @param numTests The number of tests in the suite to be run.
451    */

452   public void junitSuiteStarted(int numTests) {
453     _lock.startRead();
454     try { for (GlobalModelListener l : _listeners) { l.junitSuiteStarted(numTests); } }
455     finally { _lock.endRead(); }
456   }
457
458   /** Called when a particular test is started.
459    * @param name The name of the test being started.
460    */

461   public void junitTestStarted(String JavaDoc name) {
462     _lock.startRead();
463     try { for (GlobalModelListener l : _listeners) { l.junitTestStarted(name); } }
464     finally { _lock.endRead(); }
465   }
466
467   /** Called when a particular test has ended.
468    * @param name the name of the test that has ended
469    * @param wasSuccessful whether the test passed or not
470    * @param causedError if not successful, whether the test caused an error or simply failed
471    */

472   public void junitTestEnded(String JavaDoc name, boolean wasSuccessful, boolean causedError) {
473     _lock.startRead();
474     try {
475       for (GlobalModelListener l : _listeners) { l.junitTestEnded(name, wasSuccessful, causedError); }
476     }
477     finally { _lock.endRead(); }
478   }
479
480   /** Called after JUnit is finished running tests. */
481   public void junitEnded() {
482     _lock.startRead();
483     try { for (GlobalModelListener l : _listeners) { l.junitEnded(); } }
484     finally { _lock.endRead(); }
485   }
486
487 // /** Called to demand that all files be saved before running JUnit tests. It is up to the caller of this
488
// * method to check if the documents have been saved, using IGetDocuments.hasModifiedDocuments(). This is
489
// * never called currently, but it is commented out in case it is needed later. */
490
// public void saveBeforeJUnit() {
491
// _lock.startRead();
492
// try {
493
// for (GlobalModelListener l : _listeners) {
494
// l.saveBeforeJUnit();
495
// }
496
// }
497
// finally {
498
// _lock.endRead();
499
// }
500
// }
501

502   //--------------------------------- Javadoc --------------------------------//
503

504   /** Called after Javadoc is started by the GlobalModel. */
505   public void javadocStarted() {
506     _lock.startRead();
507     try { for (GlobalModelListener l : _listeners) { l.javadocStarted(); } }
508     finally { _lock.endRead(); }
509   }
510
511   /** Called after Javadoc is finished.
512    * @param success whether the Javadoc operation generated proper output
513    * @param destDir if (success) the location where the output was generated, otherwise undefined (possibly null)
514    * @param allDocs Whether Javadoc was run for all open documents
515    */

516   public void javadocEnded(boolean success, File JavaDoc destDir, boolean allDocs) {
517     _lock.startRead();
518     try { for (GlobalModelListener l : _listeners) { l.javadocEnded(success, destDir, allDocs); } }
519     finally { _lock.endRead(); }
520   }
521
522
523   /** Called before attempting Javadoc, to give the user a chance to save. Do not continue with Javadoc if the user
524    * doesn't save!
525    */

526   public void saveBeforeJavadoc() {
527     _lock.startRead();
528     try { for (GlobalModelListener l : _listeners) { l.saveBeforeJavadoc(); } }
529     finally { _lock.endRead(); }
530   }
531
532 // /** Called to demand that all files be saved before starting the debugger. It is up to the caller of this method
533
// * to check if the documents have been saved, using IGetDocuments.hasModifiedDocuments(). This is not used
534
// * currently, but it is commented out in case it is needed later. */
535
// public void saveBeforeDebug() {
536
// _lock.startRead();
537
// try { for (GlobalModelListener l : _listeners) { l.saveBeforeDebug(); } }
538
// finally { _lock.endRead(); }
539
// }
540

541   /** Notifies the view that the current interaction is incomplete. */
542   public void interactionIncomplete() {
543     _lock.startRead();
544     try { for (GlobalModelListener l : _listeners) { l.interactionIncomplete(); } }
545     finally { _lock.endRead(); }
546   }
547   
548   public void slaveJVMUsed() {
549     _lock.startRead();
550     try { for (GlobalModelListener l : _listeners) { l.slaveJVMUsed(); } }
551     finally { _lock.endRead(); }
552   }
553
554   /** Notifies the view that the current file path contains a #. */
555   public void filePathContainsPound() {
556     _lock.startRead();
557     try { for (GlobalModelListener l : _listeners) { l.filePathContainsPound(); } }
558     finally { _lock.endRead(); }
559   }
560   
561   // ----- Cache -----
562
public void documentNotFound(OpenDefinitionsDocument d, File JavaDoc f) {
563     _lock.startRead();
564     try { for (GlobalModelListener l : _listeners) { l.documentNotFound(d,f); } }
565     finally { _lock.endRead(); }
566   }
567 }
568
Popular Tags