KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > editor > WeakEventListenerList


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.editor;
21
22 import java.lang.ref.WeakReference JavaDoc;
23 import java.lang.reflect.Array JavaDoc;
24 import java.lang.reflect.Array JavaDoc;
25 import java.io.ObjectInputStream JavaDoc;
26 import java.io.ObjectOutputStream JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.Serializable JavaDoc;
29 import java.util.EventListener JavaDoc;
30 import javax.swing.event.EventListenerList JavaDoc;
31
32 /**
33 * Class that can hold the list of event listeners
34 * in a "weak" manner. The advantage is that the listener
35 * doesn't need to be explicitly removed. Because of the use
36 * of the <tt>WeakReference</tt> it gets forgotten
37 * automatically if it was garbage collected. There must
38 * be at least one non-weak reference to the listener
39 * (otherwise it would become garbage-collected).
40 * One of the ways is to store the listener in some instance
41 * variable in the class that adds the listener.
42 * Please note that the methods <tt>getListenerCount()</tt>
43 * and <tt>getListenerCount(Class t)</tt> give the count
44 * that doesn't reflect whether some listeners were garbage
45 * collected.
46 *
47 * @author Miloslav Metelka
48 * @version 1.00
49 */

50
51 public class WeakEventListenerList extends EventListenerList JavaDoc {
52
53     private int listenerSize;
54
55     /**
56     *
57     */

58     public synchronized Object JavaDoc[] getListenerList() {
59         int tgtInd = 0;
60         Object JavaDoc[] ret = new Object JavaDoc[listenerSize];
61         for (int i = 1; i < listenerSize; i += 2) {
62             Object JavaDoc l = ((WeakReference JavaDoc)listenerList[i]).get();
63             if (l != null) {
64                 ret[tgtInd++] = listenerList[i - 1];
65                 ret[tgtInd++] = l;
66             } else { // listener was garbage collected
67
/* Remove the listener and its class. This could be done
68                 * in a more efficient but much less readable way batching
69                 * the successive removes into one.
70                 */

71                 System.arraycopy(listenerList, i + 1, listenerList, i - 1,
72                                  listenerSize - i - 1);
73                 listenerSize -= 2;
74                 i -= 2;
75             }
76         }
77
78         if (ret.length != tgtInd) {
79             Object JavaDoc[] tmp = new Object JavaDoc[tgtInd];
80             System.arraycopy(ret, 0, tmp, 0, tgtInd);
81             ret = tmp;
82         }
83
84         return ret;
85     }
86
87     public synchronized EventListener JavaDoc[] getListeners(Class JavaDoc t) {
88         int tgtInd = 0;
89         EventListener JavaDoc[] ret = (EventListener JavaDoc[])Array.newInstance(t, listenerSize);
90         for (int i = 0; i < listenerSize; i++) {
91             if (listenerList[i++] == t) {
92                 EventListener JavaDoc l = (EventListener JavaDoc)((WeakReference JavaDoc)listenerList[i]).get();
93                 if (l != null) {
94                     ret[tgtInd++] = l;
95                 } else { // listener was garbage collected
96
/* Remove the listener and its class. This could be done
97                     * in a more efficient but much less readable way batching
98                     * the successive removes into one.
99                     */

100                     System.arraycopy(listenerList, i + 1, listenerList, i - 1,
101                                      listenerSize - i - 1);
102                     listenerSize -= 2;
103                     i -= 2;
104                 }
105             }
106         }
107
108         if (ret.length != tgtInd) {
109             EventListener JavaDoc[] tmp = (EventListener JavaDoc[])Array.newInstance(t, tgtInd);
110             System.arraycopy(ret, 0, tmp, 0, tgtInd);
111             ret = tmp;
112         }
113
114         return ret;
115     }
116
117
118     /**
119      * Adds the listener as a listener of the specified type.
120      * @param t the type of the listener to be added
121      * @param l the listener to be added
122      */

123     public synchronized void add(Class JavaDoc t, EventListener JavaDoc l) {
124         if (l==null) {
125             // In an ideal world, we would do an assertion here
126
// to help developers know they are probably doing
127
// something wrong
128
return;
129         }
130
131         if (!t.isInstance(l)) {
132             throw new IllegalArgumentException JavaDoc("Listener " + l + // NOI18N
133
" is not of type " + t); // NOI18N
134
}
135
136         if (listenerSize == 0) {
137             listenerList = new Object JavaDoc[] { t, new WeakReference JavaDoc(l) };
138             listenerSize = 2;
139         } else {
140             if (listenerSize == listenerList.length) { // reallocate
141
Object JavaDoc[] tmp = new Object JavaDoc[listenerSize * 2];
142                 System.arraycopy(listenerList, 0, tmp, 0, listenerSize);
143                 listenerList = tmp;
144             }
145
146             listenerList[listenerSize++] = t;
147             listenerList[listenerSize++] = new WeakReference JavaDoc(l);
148         }
149     }
150
151     /**
152      * Removes the listener as a listener of the specified type.
153      * @param t the type of the listener to be removed
154      * @param l the listener to be removed
155      */

156     public synchronized void remove(Class JavaDoc t, EventListener JavaDoc l) {
157         if (l ==null) {
158             // In an ideal world, we would do an assertion here
159
// to help developers know they are probably doing
160
// something wrong
161
return;
162         }
163
164         if (!t.isInstance(l)) {
165             throw new IllegalArgumentException JavaDoc("Listener " + l + // NOI18N
166
" is not of type " + t); // NOI18N
167
}
168
169         // Is l on the list?
170
int index = -1;
171         for (int i = listenerSize - 2; i >= 0; i -= 2) {
172             if ((listenerList[i] == t)
173                     && l == ((WeakReference JavaDoc)listenerList[ i + 1]).get()
174                ) {
175                 index = i;
176                 break;
177             }
178         }
179
180         // If so, remove it
181
if (index >= 0) {
182             System.arraycopy(listenerList, index + 2, listenerList, index,
183                              listenerSize - index - 2);
184             listenerSize -= 2;
185         }
186     }
187
188     private synchronized void writeObject(ObjectOutputStream JavaDoc os) throws IOException JavaDoc {
189         os.defaultWriteObject();
190
191         // Save the non-null event listeners:
192
for (int i = 0; i < listenerSize; i += 2) {
193             Class JavaDoc t = (Class JavaDoc)listenerList[i];
194             EventListener JavaDoc l = (EventListener JavaDoc)((WeakReference JavaDoc)listenerList[i + 1]).get();
195             if ((l != null) && (l instanceof Serializable JavaDoc)) {
196                 os.writeObject(t.getName());
197                 os.writeObject(l);
198             }
199         }
200
201         os.writeObject(null);
202     }
203
204     private void readObject(ObjectInputStream JavaDoc is)
205     throws IOException JavaDoc, ClassNotFoundException JavaDoc {
206         is.defaultReadObject();
207         Object JavaDoc listenerTypeOrNull;
208
209         while (null != (listenerTypeOrNull = is.readObject())) {
210             EventListener JavaDoc l = (EventListener JavaDoc)is.readObject();
211             add(Class.forName((String JavaDoc)listenerTypeOrNull), l);
212         }
213     }
214
215     public synchronized String JavaDoc toString() {
216         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("WeakEventListenerList: "); // NOI18N
217
sb.append(listenerSize / 2);
218         sb.append(" listeners:\n"); // NOI18N
219
for (int i = 0; i < listenerSize; i += 2) {
220             sb.append(" type " + ((Class JavaDoc)listenerList[i]).getName()); // NOI18N
221
sb.append(" listener " + ((WeakReference JavaDoc)listenerList[i + 1]).get()); // NOI18N
222
}
223         return sb.toString();
224     }
225
226 }
227
Popular Tags