KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > util > WeakListener


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 package org.openide.util;
20
21 import java.util.logging.Logger JavaDoc;
22 import org.openide.filesystems.*;
23 import org.openide.nodes.*;
24
25 import java.awt.event.FocusEvent JavaDoc;
26 import java.awt.event.FocusListener JavaDoc;
27
28 import java.beans.*;
29
30 import java.lang.ref.*;
31 import java.lang.reflect.*;
32
33 import java.util.EventListener JavaDoc;
34 import java.util.EventObject JavaDoc;
35 import java.util.logging.Level JavaDoc;
36
37 import javax.swing.event.*;
38
39
40 /**
41  * @deprecated Use {@link org.openide.util.WeakListeners} class.
42  * @author Jaroslav Tulach
43  */

44 public abstract class WeakListener implements java.util.EventListener JavaDoc {
45     /** weak reference to listener */
46     private Reference ref;
47
48     /** class of the listener */
49     Class JavaDoc listenerClass;
50
51     /** weak reference to source */
52     private Reference source;
53
54     /**
55      * @param listenerClass class/interface of the listener
56      * @param l listener to delegate to, <code>l</code> must be an instance of
57      * listenerClass
58      */

59     protected WeakListener(Class JavaDoc listenerClass, java.util.EventListener JavaDoc l) {
60         this.listenerClass = listenerClass;
61         ref = new ListenerReference(l, this);
62
63         if (!listenerClass.isAssignableFrom(l.getClass())) {
64             throw new IllegalArgumentException JavaDoc(
65                 getClass().getName() + " constructor is calling WeakListner.<init> with illegal arguments"
66             ); // NOI18N
67
}
68     }
69
70     /** Setter for the source field. If a WeakReference to an underlying listener is
71      * cleared and enqueued, that is, the original listener is garbage collected,
72      * then the source field is used for deregistration of this WeakListener, thus making
73      * it eligible for garbage collection if no more references exist.
74      *
75      * This method is particularly useful in cases where the underlying listener was
76      * garbage collected and the event source, on which this listener is listening on,
77      * is quiet, i.e. does not fire any events for long periods. In this case, this listener
78      * is not removed from the event source until an event is fired. If the source field is
79      * set however, org.openide.util.WeakListeners that lost their underlying listeners are removed
80      * as soon as the ReferenceQueue notifies the WeakListener.
81      *
82      * @param source is any Object or <code>null</code>, though only setting an object
83      * that has an appropriate remove*listenerClass*Listener method and on which this listener is listening on,
84      * is useful.
85      */

86     protected final void setSource(Object JavaDoc source) {
87         if (source == null) {
88             this.source = null;
89         } else {
90             this.source = new WeakReference(source);
91         }
92     }
93
94     /** Method name to use for removing the listener.
95     * @return name of method of the source object that should be used
96     * to remove the listener from listening on source of events
97     */

98     protected abstract String JavaDoc removeMethodName();
99
100     /** Getter for the target listener.
101     * @param ev the event the we want to distribute
102     * @return null if there is no listener because it has been finalized
103     */

104     protected final java.util.EventListener JavaDoc get(java.util.EventObject JavaDoc ev) {
105         Object JavaDoc l = ref.get(); // get the consumer
106

107         // if the event consumer is gone, unregister us from the event producer
108
if (l == null) {
109             removeListener((ev == null) ? null : ev.getSource());
110         }
111
112         return (EventListener JavaDoc) l;
113     }
114
115     /** Tries to find a remove method and invoke it.
116      * It tries unregister itself from the registered source first
117      * and then from the passed eventSource if they are not same.
118      *
119      * @param eventSource the source object to unregister from or null
120      */

121     private void removeListener(Object JavaDoc eventSource) {
122         Object JavaDoc[] params = new Object JavaDoc[] { getImplementator() };
123         Object JavaDoc src = (source == null) ? null : source.get();
124
125         try {
126             Method m = null;
127
128             if (src != null) {
129                 m = getRemoveMethod(src.getClass(), removeMethodName(), listenerClass);
130
131                 if (m != null) {
132                     m.invoke(src, params);
133                 }
134             }
135
136             if ((eventSource != src) && (eventSource != null)) {
137                 m = getRemoveMethod(eventSource.getClass(), removeMethodName(), listenerClass);
138
139                 if (m != null) {
140                     m.invoke(eventSource, params);
141                 }
142             }
143
144             if ((m == null) && (source == null)) { // can't remove the listener
145
Logger.getAnonymousLogger().warning(
146                     "Can't remove " + listenerClass.getName() + //NOI18N
147
" using method " + removeMethodName() + //NOI18N
148
" source=" + source + //NOI18N
149
", SRC=" + src + ", eventSource=" + eventSource
150                 ); //NOI18N
151
}
152         } catch (Exception JavaDoc ex) { // from invoke(), should not happen
153
Logger.getLogger(WeakListener.class.getName()).log(Level.WARNING, null, ex);
154         }
155     }
156
157     /* can return null */
158     private static final Method getRemoveMethod(Class JavaDoc methodClass, String JavaDoc methodName, Class JavaDoc listenerClass) {
159         final Class JavaDoc[] clarray = new Class JavaDoc[] { listenerClass };
160         Method m = null;
161
162         try {
163             m = methodClass.getMethod(methodName, clarray);
164         } catch (NoSuchMethodException JavaDoc e) {
165             do {
166                 try {
167                     m = methodClass.getDeclaredMethod(methodName, clarray);
168                 } catch (NoSuchMethodException JavaDoc ex) {
169                 }
170
171                 methodClass = methodClass.getSuperclass();
172             } while ((m == null) && (methodClass != Object JavaDoc.class));
173         }
174
175         if (
176             (m != null) &&
177                 (!Modifier.isPublic(m.getModifiers()) || !Modifier.isPublic(m.getDeclaringClass().getModifiers()))
178         ) {
179             m.setAccessible(true);
180         }
181
182         return m;
183     }
184
185     Object JavaDoc getImplementator() {
186         return this;
187     }
188
189     public String JavaDoc toString() {
190         Object JavaDoc listener = ref.get();
191
192         return getClass().getName() + "[" + ((listener == null) ? "null" : (listener.getClass().getName() + "]"));
193     }
194
195     //
196
// Methods for establishing connections
197
//
198

199     /** Creates a weak implementation of NodeListener.
200      *
201      * @param l the listener to delegate to
202      * @param source the source that the listener should detach from when
203      * listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
204      * @return a NodeListener delegating to <CODE>l</CODE>.
205      * @deprecated Use {@link org.openide.nodes.NodeOp#weakNodeListener} or {@link org.openide.util.WeakListeners#create}
206      */

207     public static NodeListener node(NodeListener l, Object JavaDoc source) {
208         WeakListener.Node wl = new WeakListener.Node(l);
209         wl.setSource(source);
210
211         return wl;
212     }
213
214     /** Creates a weak implementation of PropertyChangeListener.
215      *
216      * @param l the listener to delegate to
217      * @param source the source that the listener should detach from when
218      * listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
219      * @return a PropertyChangeListener delegating to <CODE>l</CODE>.
220      * @deprecated Use {@link org.openide.util.WeakListeners#propertyChange}
221      */

222     public static PropertyChangeListener propertyChange(PropertyChangeListener l, Object JavaDoc source) {
223         WeakListener.PropertyChange wl = new WeakListener.PropertyChange(l);
224         wl.setSource(source);
225
226         return wl;
227     }
228
229     /** Creates a weak implementation of VetoableChangeListener.
230      *
231      * @param l the listener to delegate to
232      * @param source the source that the listener should detach from when
233      * listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
234      * @return a VetoableChangeListener delegating to <CODE>l</CODE>.
235      * @deprecated Use {@link org.openide.util.WeakListeners#vetoableChange}
236      */

237     public static VetoableChangeListener vetoableChange(VetoableChangeListener l, Object JavaDoc source) {
238         WeakListener.VetoableChange wl = new WeakListener.VetoableChange(l);
239         wl.setSource(source);
240
241         return wl;
242     }
243
244     /** Creates a weak implementation of FileChangeListener.
245      *
246      * @param l the listener to delegate to
247      * @param source the source that the listener should detach from when
248      * listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
249      * @return a FileChangeListener delegating to <CODE>l</CODE>.
250      * @deprecated Use {@link FileUtil#weakFileChangeListener} or {@link org.openide.util.WeakListeners#create}
251      */

252     public static FileChangeListener fileChange(FileChangeListener l, Object JavaDoc source) {
253         WeakListener.FileChange wl = new WeakListener.FileChange(l);
254         wl.setSource(source);
255
256         return wl;
257     }
258
259     /** Creates a weak implementation of FileStatusListener.
260      *
261      * @param l the listener to delegate to
262      * @param source the source that the listener should detach from when
263      * listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
264      * @return a FileStatusListener delegating to <CODE>l</CODE>.
265      * @deprecated Use {@link FileUtil#weakFileStatusListener} or {@link org.openide.util.WeakListeners#create}
266      */

267     public static FileStatusListener fileStatus(FileStatusListener l, Object JavaDoc source) {
268         WeakListener.FileStatus wl = new WeakListener.FileStatus(l);
269         wl.setSource(source);
270
271         return wl;
272     }
273
274     /** Creates a weak implementation of RepositoryListener.
275      *
276      * @param l the listener to delegate to
277      * @param source the source that the listener should detach from when
278      * listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
279      * @return a RepositoryListener delegating to <CODE>l</CODE>.
280      */

281     public static RepositoryListener repository(RepositoryListener l, Object JavaDoc source) {
282         WeakListener.Repository wl = new WeakListener.Repository(l);
283         wl.setSource(source);
284
285         return wl;
286     }
287
288     /** Creates a weak implementation of DocumentListener.
289      *
290      * @param l the listener to delegate to
291      * @param source the source that the listener should detach from when
292      * listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
293      * @return a DocumentListener delegating to <CODE>l</CODE>.
294      * @deprecated Use {@link org.openide.util.WeakListeners#document}
295      */

296     public static DocumentListener document(DocumentListener l, Object JavaDoc source) {
297         WeakListener.Document wl = new WeakListener.Document(l);
298         wl.setSource(source);
299
300         return wl;
301     }
302
303     /** Creates a weak implementation of ChangeListener.
304      *
305      * @param l the listener to delegate to
306      * @param source the source that the listener should detach from when
307      * listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
308      * @return a ChangeListener delegating to <CODE>l</CODE>.
309      * @deprecated Use {@link org.openide.util.WeakListeners#change}
310      */

311     public static ChangeListener change(ChangeListener l, Object JavaDoc source) {
312         WeakListener.Change wl = new WeakListener.Change(l);
313         wl.setSource(source);
314
315         return wl;
316     }
317
318     /** Creates a weak implementation of FocusListener.
319      *
320      * @param l the listener to delegate to
321      * @param source the source that the listener should detach from when
322      * listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
323      * @return a FocusListener delegating to <CODE>l</CODE>.
324      * @deprecated Use {@link org.openide.util.WeakListeners#create}
325      */

326     public static FocusListener JavaDoc focus(FocusListener JavaDoc l, Object JavaDoc source) {
327         WeakListener.Focus wl = new WeakListener.Focus(l);
328         wl.setSource(source);
329
330         return wl;
331     }
332
333     /** A generic WeakListener factory.
334      * Creates a weak implementation of a listener of type <CODE>lType</CODE>.
335      *
336      * @param lType the type of listener to create. It can be any interface,
337      * but only interfaces are allowed.
338      * @param l the listener to delegate to, <CODE>l</CODE> must be an instance
339      * of <CODE>lType</CODE>
340      * @param source the source that the listener should detach from when
341      * listener <CODE>l</CODE> is freed, can be <CODE>null</CODE>
342      * @return an instance of <CODE>lType</CODE> delegating all the interface
343      * calls to <CODE>l</CODE>.
344      * @deprecated Use {@link org.openide.util.WeakListeners#create}
345      */

346     public static EventListener JavaDoc create(Class JavaDoc lType, EventListener JavaDoc l, Object JavaDoc source) {
347         ProxyListener pl = new ProxyListener(lType, l);
348         pl.setSource(source);
349
350         return (EventListener JavaDoc) pl.proxy;
351     }
352
353     /** Weak property change listener
354     * @deprecated use appropriate method instead
355     */

356     public static class PropertyChange extends WeakListener implements PropertyChangeListener {
357         /** Constructor.
358         * @param l listener to delegate to
359         */

360         public PropertyChange(PropertyChangeListener l) {
361             super(PropertyChangeListener.class, l);
362         }
363
364         /** Constructor.
365         * @param clazz required class
366         * @param l listener to delegate to
367         */

368         PropertyChange(Class JavaDoc clazz, PropertyChangeListener l) {
369             super(clazz, l);
370         }
371
372         /** Tests if the object we reference to still exists and
373         * if so, delegate to it. Otherwise remove from the source
374         * if it has removePropertyChangeListener method.
375         */

376         public void propertyChange(PropertyChangeEvent ev) {
377             PropertyChangeListener l = (PropertyChangeListener) super.get(ev);
378
379             if (l != null) {
380                 l.propertyChange(ev);
381             }
382         }
383
384         /** Method name to use for removing the listener.
385         * @return name of method of the source object that should be used
386         * to remove the listener from listening on source of events
387         */

388         protected String JavaDoc removeMethodName() {
389             return "removePropertyChangeListener"; // NOI18N
390
}
391     }
392
393     /** Weak vetoable change listener
394     * @deprecated use appropriate method instead
395     */

396     public static class VetoableChange extends WeakListener implements VetoableChangeListener {
397         /** Constructor.
398         * @param l listener to delegate to
399         */

400         public VetoableChange(VetoableChangeListener l) {
401             super(VetoableChangeListener.class, l);
402         }
403
404         /** Tests if the object we reference to still exists and
405         * if so, delegate to it. Otherwise remove from the source
406         * if it has removePropertyChangeListener method.
407         */

408         public void vetoableChange(PropertyChangeEvent ev)
409         throws PropertyVetoException {
410             VetoableChangeListener l = (VetoableChangeListener) super.get(ev);
411
412             if (l != null) {
413                 l.vetoableChange(ev);
414             }
415         }
416
417         /** Method name to use for removing the listener.
418         * @return name of method of the source object that should be used
419         * to remove the listener from listening on source of events
420         */

421         protected String JavaDoc removeMethodName() {
422             return "removeVetoableChangeListener"; // NOI18N
423
}
424     }
425
426     /** Weak file change listener.
427     * @deprecated use appropriate method instead
428     */

429     public static class FileChange extends WeakListener implements FileChangeListener {
430         /** Constructor.
431         * @param l listener to delegate to
432         */

433         public FileChange(FileChangeListener l) {
434             super(FileChangeListener.class, l);
435         }
436
437         /** Fired when a new folder has been created. This action can only be
438         * listened in folders containing the created file up to the root of
439         * file system.
440         *
441         * @param ev the event describing context where action has taken place
442         */

443         public void fileFolderCreated(FileEvent ev) {
444             FileChangeListener l = (FileChangeListener) super.get(ev);
445
446             if (l != null) {
447                 l.fileFolderCreated(ev);
448             }
449         }
450
451         /** Fired when a new file has been created. This action can only be
452         * listened in folders containing the created file up to the root of
453         * file system.
454         *
455         * @param ev the event describing context where action has taken place
456         */

457         public void fileDataCreated(FileEvent ev) {
458             FileChangeListener l = (FileChangeListener) super.get(ev);
459
460             if (l != null) {
461                 l.fileDataCreated(ev);
462             }
463         }
464
465         /** Fired when a file has been changed.
466         * @param ev the event describing context where action has taken place
467         */

468         public void fileChanged(FileEvent ev) {
469             FileChangeListener l = (FileChangeListener) super.get(ev);
470
471             if (l != null) {
472                 l.fileChanged(ev);
473             }
474         }
475
476         /** Fired when a file has been deleted.
477         * @param ev the event describing context where action has taken place
478         */

479         public void fileDeleted(FileEvent ev) {
480             FileChangeListener l = (FileChangeListener) super.get(ev);
481
482             if (l != null) {
483                 l.fileDeleted(ev);
484             }
485         }
486
487         /** Fired when a file has been renamed.
488         * @param ev the event describing context where action has taken place
489         * and the original name and extension.
490         */

491         public void fileRenamed(FileRenameEvent ev) {
492             FileChangeListener l = (FileChangeListener) super.get(ev);
493
494             if (l != null) {
495                 l.fileRenamed(ev);
496             }
497         }
498
499         /** Fired when a file attribute has been changed.
500         * @param ev the event describing context where action has taken place,
501         * the name of attribute and old and new value.
502         */

503         public void fileAttributeChanged(FileAttributeEvent ev) {
504             FileChangeListener l = (FileChangeListener) super.get(ev);
505
506             if (l != null) {
507                 l.fileAttributeChanged(ev);
508             }
509         }
510
511         /** Method name to use for removing the listener.
512         * @return name of method of the source object that should be used
513         * to remove the listener from listening on source of events
514         */

515         protected String JavaDoc removeMethodName() {
516             return "removeFileChangeListener"; // NOI18N
517
}
518     }
519
520     /** Weak file status listener.
521     * @deprecated use appropriate method instead
522     */

523     public static class FileStatus extends WeakListener implements FileStatusListener {
524         /** Constructor.
525         */

526         public FileStatus(FileStatusListener l) {
527             super(FileStatusListener.class, l);
528         }
529
530         /** Notifies listener about change in annotataion of a few files.
531          * @param ev event describing the change
532          */

533         public void annotationChanged(FileStatusEvent ev) {
534             FileStatusListener l = (FileStatusListener) super.get(ev);
535
536             if (l != null) {
537                 l.annotationChanged(ev);
538             }
539         }
540
541         /** Method name to use for removing the listener.
542         * @return name of method of the source object that should be used
543         * to remove the listener from listening on source of events
544         */

545         protected String JavaDoc removeMethodName() {
546             return "removeFileStatusListener"; // NOI18N
547
}
548     }
549
550     /** Weak file system pool listener.
551     * @deprecated use appropriate method instead
552     */

553     public static class Repository extends WeakListener implements RepositoryListener {
554         /** Constructor.
555         * @param l listener to delegate to
556         */

557         public Repository(RepositoryListener l) {
558             super(RepositoryListener.class, l);
559         }
560
561         /** Called when new file system is added to the pool.
562         * @param ev event describing the action
563         */

564         public void fileSystemAdded(RepositoryEvent ev) {
565             RepositoryListener l = (RepositoryListener) super.get(ev);
566
567             if (l != null) {
568                 l.fileSystemAdded(ev);
569             }
570         }
571
572         /** Called when a file system is deleted from the pool.
573         * @param ev event describing the action
574         */

575         public void fileSystemRemoved(RepositoryEvent ev) {
576             RepositoryListener l = (RepositoryListener) super.get(ev);
577
578             if (l != null) {
579                 l.fileSystemRemoved(ev);
580             }
581         }
582
583         /** Called when a Repository is reordered. */
584         public void fileSystemPoolReordered(RepositoryReorderedEvent ev) {
585             RepositoryListener l = (RepositoryListener) super.get(ev);
586
587             if (l != null) {
588                 l.fileSystemPoolReordered(ev);
589             }
590         }
591
592         /** Method name to use for removing the listener.
593         * @return name of method of the source object that should be used
594         * to remove the listener from listening on source of events
595         */

596         protected String JavaDoc removeMethodName() {
597             return "removeRepositoryListener"; // NOI18N
598
}
599     }
600
601     /** Weak document modifications listener.
602     * This class if final only for performance reasons,
603     * can be happily unfinaled if desired.
604     * @deprecated use appropriate method instead
605     */

606     public static final class Document extends WeakListener implements DocumentListener {
607         /** Constructor.
608         * @param l listener to delegate to
609         */

610         public Document(final DocumentListener l) {
611             super(DocumentListener.class, l);
612         }
613
614         /** Gives notification that an attribute or set of attributes changed.
615         * @param ev event describing the action
616         */

617         public void changedUpdate(DocumentEvent ev) {
618             final DocumentListener l = docGet(ev);
619
620             if (l != null) {
621                 l.changedUpdate(ev);
622             }
623         }
624
625         /** Gives notification that there was an insert into the document.
626         * @param ev event describing the action
627         */

628         public void insertUpdate(DocumentEvent ev) {
629             final DocumentListener l = docGet(ev);
630
631             if (l != null) {
632                 l.insertUpdate(ev);
633             }
634         }
635
636         /** Gives notification that a portion of the document has been removed.
637         * @param ev event describing the action
638         */

639         public void removeUpdate(DocumentEvent ev) {
640             final DocumentListener l = docGet(ev);
641
642             if (l != null) {
643                 l.removeUpdate(ev);
644             }
645         }
646
647         /** Method name to use for removing the listener.
648         * @return name of method of the source object that should be used
649         * to remove the listener from listening on source of events
650         */

651         protected String JavaDoc removeMethodName() {
652             return "removeDocumentListener"; // NOI18N
653
}
654
655         /** Getter for the target listener.
656         * @param event the event the we want to distribute
657         * @return null if there is no listener because it has been finalized
658         */

659         private DocumentListener docGet(DocumentEvent ev) {
660             DocumentListener l = (DocumentListener) super.ref.get();
661
662             if (l == null) {
663                 super.removeListener(ev.getDocument());
664             }
665
666             return l;
667         }
668     }
669      // end of Document inner class
670

671     /** Weak swing change listener.
672     * This class if final only for performance reasons,
673     * can be happily unfinaled if desired.
674     * @deprecated use appropriate method instead
675     */

676     public static final class Change extends WeakListener implements ChangeListener {
677         /** Constructor.
678         * @param l listener to delegate to
679         */

680         public Change(ChangeListener l) {
681             super(ChangeListener.class, l);
682         }
683
684         /** Called when new file system is added to the pool.
685         * @param ev event describing the action
686         */

687         public void stateChanged(final ChangeEvent ev) {
688             ChangeListener l = (ChangeListener) super.get(ev);
689
690             if (l != null) {
691                 l.stateChanged(ev);
692             }
693         }
694
695         /** Method name to use for removing the listener.
696         * @return name of method of the source object that should be used
697         * to remove the listener from listening on source of events
698         */

699         protected String JavaDoc removeMethodName() {
700             return "removeChangeListener"; // NOI18N
701
}
702     }
703
704     /** Weak version of listener for changes in one node.
705     * This class if final only for performance reasons,
706     * can be happily unfinaled if desired.
707     * @deprecated use appropriate method instead
708     */

709     public static final class Node extends WeakListener.PropertyChange implements NodeListener {
710         /** Constructor.
711         * @param l listener to delegate to
712         */

713         public Node(NodeListener l) {
714             super(NodeListener.class, l);
715         }
716
717         /** Delegates to the original listener.
718         */

719         public void childrenAdded(NodeMemberEvent ev) {
720             NodeListener l = (NodeListener) super.get(ev);
721
722             if (l != null) {
723                 l.childrenAdded(ev);
724             }
725         }
726
727         /** Delegates to the original listener.
728         */

729         public void childrenRemoved(NodeMemberEvent ev) {
730             NodeListener l = (NodeListener) super.get(ev);
731
732             if (l != null) {
733                 l.childrenRemoved(ev);
734             }
735         }
736
737         /** Delegates to the original listener.
738         */

739         public void childrenReordered(NodeReorderEvent ev) {
740             NodeListener l = (NodeListener) super.get(ev);
741
742             if (l != null) {
743                 l.childrenReordered(ev);
744             }
745         }
746
747         /** Delegates to the original listener.
748         */

749         public void nodeDestroyed(NodeEvent ev) {
750             NodeListener l = (NodeListener) super.get(ev);
751
752             if (l != null) {
753                 l.nodeDestroyed(ev);
754             }
755         }
756
757         /** Method name to use for removing the listener.
758         * @return name of method of the source object that should be used
759         * to remove the listener from listening on source of events
760         */

761         protected String JavaDoc removeMethodName() {
762             return "removeNodeListener"; // NOI18N
763
}
764     }
765
766     /** Weak version of focus listener.
767     * This class if final only for performance reasons,
768     * can be happily unfinaled if desired.
769     * @deprecated use appropriate method instead
770     */

771     public static final class Focus extends WeakListener implements FocusListener JavaDoc {
772         /** Constructor.
773         * @param l listener to delegate to
774         */

775         public Focus(FocusListener JavaDoc l) {
776             super(FocusListener JavaDoc.class, l);
777         }
778
779         /** Delegates to the original listener.
780         */

781         public void focusGained(FocusEvent JavaDoc ev) {
782             FocusListener JavaDoc l = (FocusListener JavaDoc) super.get(ev);
783
784             if (l != null) {
785                 l.focusGained(ev);
786             }
787         }
788
789         /** Delegates to the original listener.
790         */

791         public void focusLost(FocusEvent JavaDoc ev) {
792             FocusListener JavaDoc l = (FocusListener JavaDoc) super.get(ev);
793
794             if (l != null) {
795                 l.focusLost(ev);
796             }
797         }
798
799         /** Method name to use for removing the listener.
800         * @return name of method of the source object that should be used
801         * to remove the listener from listening on source of events
802         */

803         protected String JavaDoc removeMethodName() {
804             return "removeFocusListener"; // NOI18N
805
}
806     }
807
808     /** Proxy interface that delegates to listeners.
809     */

810     private static class ProxyListener extends WeakListener implements InvocationHandler {
811         /** Equals method */
812         private static Method equalsMth;
813
814         /** proxy generated for this listener */
815         public final Object JavaDoc proxy;
816
817         /** @param listener listener to delegate to
818         */

819         public ProxyListener(Class JavaDoc c, java.util.EventListener JavaDoc listener) {
820             super(c, listener);
821
822             proxy = Proxy.newProxyInstance(c.getClassLoader(), new Class JavaDoc[] { c }, this);
823         }
824
825         /** */
826         private static Method getEquals() {
827             if (equalsMth == null) {
828                 try {
829                     equalsMth = Object JavaDoc.class.getMethod("equals", new Class JavaDoc[] { Object JavaDoc.class }); // NOI18N
830
} catch (NoSuchMethodException JavaDoc e) {
831                     e.printStackTrace();
832                 }
833             }
834
835             return equalsMth;
836         }
837
838         public java.lang.Object JavaDoc invoke(Object JavaDoc proxy, Method method, Object JavaDoc[] args)
839         throws Throwable JavaDoc {
840             if (method.getDeclaringClass() == Object JavaDoc.class) {
841                 // a method from object => call it on your self
842
if (method == getEquals()) {
843                     boolean ret = equals(args[0]);
844
845                     return (ret ? Boolean.TRUE : Boolean.FALSE);
846                 }
847
848                 return method.invoke(this, args);
849             }
850
851             // listeners method
852
EventObject JavaDoc ev = (args[0] instanceof EventObject JavaDoc) ? (EventObject JavaDoc) args[0] : null;
853
854             Object JavaDoc listener = super.get(ev);
855
856             if (listener != null) {
857                 return method.invoke(listener, args);
858             } else {
859                 return null;
860             }
861         }
862
863         /** Remove method name is composed from the name of the listener.
864         */

865         protected String JavaDoc removeMethodName() {
866             String JavaDoc name = listenerClass.getName();
867
868             // strip package name
869
int dot = name.lastIndexOf('.');
870             name = name.substring(dot + 1);
871
872             // in case of inner interfaces/classes we also strip the outer
873
// class' name
874
int i = name.lastIndexOf('$'); // NOI18N
875

876             if (i >= 0) {
877                 name = name.substring(i + 1);
878             }
879
880             return "remove".concat(name); // NOI18N
881
}
882
883         /** To string prints class.
884         */

885         public String JavaDoc toString() {
886             return super.toString() + "[" + listenerClass + "]"; // NOI18N
887
}
888
889         /** Equal is extended to equal also with proxy object.
890         */

891         public boolean equals(Object JavaDoc obj) {
892             return (proxy == obj) || (this == obj);
893         }
894
895         Object JavaDoc getImplementator() {
896             return proxy;
897         }
898     }
899
900     /** Reference that also holds ref to WeakListener.
901     */

902     private static final class ListenerReference extends WeakReference implements Runnable JavaDoc {
903         private static Class JavaDoc lastClass;
904         private static String JavaDoc lastMethodName;
905         private static Method lastRemove;
906         private static Object JavaDoc LOCK = new Object JavaDoc();
907         final WeakListener weakListener;
908
909         public ListenerReference(Object JavaDoc ref, WeakListener weakListener) {
910             super(ref, Utilities.activeReferenceQueue());
911             this.weakListener = weakListener;
912         }
913
914         public void run() {
915             ListenerReference lr = this;
916
917             // prepare array for passing arguments to getMethod/invoke
918
Object JavaDoc[] params = new Object JavaDoc[1];
919             Class JavaDoc[] types = new Class JavaDoc[1];
920             Object JavaDoc src = null; // On whom we're listening
921
Method remove = null;
922
923             WeakListener ref = lr.weakListener;
924
925             if ((ref.source == null) || ((src = ref.source.get()) == null)) {
926                 return;
927             }
928
929             Class JavaDoc methodClass = src.getClass();
930             String JavaDoc methodName = ref.removeMethodName();
931
932             synchronized (LOCK) {
933                 if ((lastClass == methodClass) && (lastMethodName == methodName) && (lastRemove != null)) {
934                     remove = lastRemove;
935                 }
936             }
937
938             // get the remove method or use the last one
939
if (remove == null) {
940                 types[0] = ref.listenerClass;
941                 remove = getRemoveMethod(methodClass, methodName, types[0]);
942
943                 if (remove == null) {
944                     Logger.getAnonymousLogger().warning(
945                         "Can't remove " + ref.listenerClass.getName() + //NOI18N
946
" using method " + methodName + //NOI18N
947
" from " + src
948                     ); //NOI18N
949

950                     return;
951                 } else {
952                     synchronized (LOCK) {
953                         lastClass = methodClass;
954                         lastMethodName = methodName;
955                         lastRemove = remove;
956                     }
957                 }
958             }
959
960             params[0] = ref.getImplementator(); // Whom to unregister
961

962             try {
963                 remove.invoke(src, params);
964             } catch (Exception JavaDoc ex) { // from invoke(), should not happen
965
Exceptions.attachLocalizedMessage(ex,
966                                                   "Problem encountered while calling " +
967                                                   methodClass + "." + methodName +
968                                                   "(...) on " + src); // NOI18N
969
Logger.getAnonymousLogger().log(Level.WARNING, null, ex);
970             }
971         }
972     }
973 }
974
Popular Tags