KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > util > lookup > SimpleProxyLookup


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.lookup;
20
21 import java.lang.ref.Reference JavaDoc;
22 import java.lang.ref.WeakReference JavaDoc;
23 import org.openide.util.Lookup;
24 import org.openide.util.LookupEvent;
25 import org.openide.util.LookupListener;
26
27 import java.util.*;
28
29
30 /**
31  * Simple proxy lookup. Keeps reference to a lookup it delegates to and
32  * forwards all requests.
33  *
34  * @author Jaroslav Tulach
35  */

36 final class SimpleProxyLookup extends org.openide.util.Lookup {
37     /** the provider to check for the status */
38     private Provider provider;
39
40     /** the lookup we currently delegate to */
41     private Lookup delegate;
42
43     /** map of all templates to Reference (results) associated to this lookup */
44     private WeakHashMap<Template<?>,Reference JavaDoc<ProxyResult<?>>> results;
45
46     /**
47      * @param provider provider to delegate to
48      */

49     SimpleProxyLookup(Provider provider) {
50         this.provider = provider;
51     }
52
53     /** Checks whether we still delegate to the same lookup */
54     private Lookup checkLookup() {
55         Lookup l = provider.getLookup();
56
57         // iterator over Reference (ProxyResult)
58
Iterator<Reference JavaDoc<ProxyResult<?>>> toCheck = null;
59
60         synchronized (this) {
61             if (l != delegate) {
62                 this.delegate = l;
63
64                 if (results != null) {
65                     toCheck = new ArrayList<Reference JavaDoc<ProxyResult<?>>>(results.values()).iterator();
66                 }
67             }
68         }
69
70         if (toCheck != null) {
71             // update
72
ArrayList<Object JavaDoc> evAndListeners = new ArrayList<Object JavaDoc>();
73             for (Iterator<Reference JavaDoc<ProxyResult<?>>> it = toCheck; it.hasNext(); ) {
74                 java.lang.ref.Reference JavaDoc<ProxyResult<?>> ref = it.next();
75                 if (ref == null) {
76                     continue;
77                 }
78
79                 ProxyResult<?> p = ref.get();
80
81                 if (p != null && p.updateLookup(l)) {
82                     p.collectFires(evAndListeners);
83                 }
84             }
85             
86             for (Iterator it = evAndListeners.iterator(); it.hasNext(); ) {
87                 LookupEvent ev = (LookupEvent)it.next();
88                 LookupListener ll = (LookupListener)it.next();
89                 ll.resultChanged(ev);
90             }
91         }
92
93         return delegate;
94     }
95
96     @SuppressWarnings JavaDoc("unchecked")
97     private static <T> ProxyResult<T> cast(ProxyResult<?> p) {
98         return (ProxyResult<T>)p;
99     }
100
101     public <T> Result<T> lookup(Template<T> template) {
102         synchronized (this) {
103             if (results == null) {
104                 results = new WeakHashMap<Template<?>,Reference JavaDoc<ProxyResult<?>>>();
105             } else {
106                 Reference JavaDoc<ProxyResult<?>> ref = results.get(template);
107
108                 if (ref != null) {
109                     ProxyResult<?> p = ref.get();
110
111                     if (p != null) {
112                         return cast(p);
113                     }
114                 }
115             }
116
117             ProxyResult<T> p = new ProxyResult<T>(template);
118             Reference JavaDoc<ProxyResult<?>> ref = new WeakReference JavaDoc<ProxyResult<?>>(p);
119             results.put(template, ref);
120
121             return p;
122         }
123     }
124
125     public <T> T lookup(Class JavaDoc<T> clazz) {
126         if (clazz == null) {
127             checkLookup();
128             return null;
129         }
130         return checkLookup().lookup(clazz);
131     }
132
133     public <T> Item<T> lookupItem(Template<T> template) {
134         return checkLookup().lookupItem(template);
135     }
136
137     /**
138      * Result used in SimpleLookup. It holds a reference to the collection
139      * passed in constructor. As the contents of this lookup result never
140      * changes the addLookupListener and removeLookupListener are empty.
141      */

142     private final class ProxyResult<T> extends WaitableResult<T> implements LookupListener {
143         /** Template used for this result. It is never null.*/
144         private Template<T> template;
145
146         /** result to delegate to */
147         private Lookup.Result<T> delegate;
148
149         /** listeners set */
150         private javax.swing.event.EventListenerList JavaDoc listeners;
151         private LookupListener lastListener;
152
153         /** Just remembers the supplied argument in variable template.*/
154         ProxyResult(Template<T> template) {
155             this.template = template;
156         }
157
158         /** Checks state of the result
159          */

160         private Result<T> checkResult() {
161             updateLookup(checkLookup());
162
163             return this.delegate;
164         }
165
166         /** Updates the state of the lookup.
167          * @return true if the lookup really changed
168          */

169         public boolean updateLookup(Lookup l) {
170             Collection<? extends Item<T>> oldPairs = (delegate != null) ? delegate.allItems() : null;
171
172             LookupListener removedListener;
173
174             synchronized (this) {
175                 if ((delegate != null) && (lastListener != null)) {
176                     removedListener = lastListener;
177                     delegate.removeLookupListener(lastListener);
178                 } else {
179                     removedListener = null;
180                 }
181             }
182
183             // cannot call to foreign code
184
Lookup.Result<T> res = l.lookup(template);
185
186             synchronized (this) {
187                 if (removedListener == lastListener) {
188                     delegate = res;
189                     lastListener = new WeakResult<T>(this, delegate);
190                     delegate.addLookupListener(lastListener);
191                 }
192             }
193
194             if (oldPairs == null) {
195                 // nobody knows about a change
196
return false;
197             }
198
199             Collection<? extends Item<T>> newPairs = delegate.allItems();
200
201             // See #34961 for explanation.
202
if (!(oldPairs instanceof List)) {
203                 if (oldPairs == Collections.EMPTY_SET) {
204                     // avoid allocation
205
oldPairs = Collections.emptyList();
206                 } else {
207                     oldPairs = new ArrayList<Item<T>>(oldPairs);
208                 }
209             }
210
211             if (!(newPairs instanceof List)) {
212                 newPairs = new ArrayList<Item<T>>(newPairs);
213             }
214
215             return !oldPairs.equals(newPairs);
216         }
217
218         public synchronized void addLookupListener(LookupListener l) {
219             if (listeners == null) {
220                 listeners = new javax.swing.event.EventListenerList JavaDoc();
221             }
222
223             listeners.add(LookupListener.class, l);
224         }
225
226         public synchronized void removeLookupListener(LookupListener l) {
227             if (listeners != null) {
228                 listeners.remove(LookupListener.class, l);
229             }
230         }
231
232         public java.util.Collection JavaDoc<? extends T> allInstances() {
233             return checkResult().allInstances();
234         }
235
236         public Set<Class JavaDoc<? extends T>> allClasses() {
237             return checkResult().allClasses();
238         }
239
240         public Collection<? extends Item<T>> allItems() {
241             return checkResult().allItems();
242         }
243
244         protected void beforeLookup(Lookup.Template t) {
245             Lookup.Result r = checkResult();
246
247             if (r instanceof WaitableResult) {
248                 ((WaitableResult) r).beforeLookup(t);
249             }
250         }
251
252         /** A change in lookup occured.
253          * @param ev event describing the change
254          *
255          */

256         public void resultChanged(LookupEvent anEvent) {
257             collectFires(null);
258         }
259         
260         protected void collectFires(Collection<Object JavaDoc> evAndListeners) {
261             javax.swing.event.EventListenerList JavaDoc l = this.listeners;
262
263             if (l == null) {
264                 return;
265             }
266
267             Object JavaDoc[] listeners = l.getListenerList();
268
269             if (listeners.length == 0) {
270                 return;
271             }
272
273             LookupEvent ev = new LookupEvent(this);
274             AbstractLookup.notifyListeners(listeners, ev, evAndListeners);
275         }
276     }
277      // end of ProxyResult
278
private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
279         private Lookup.Result source;
280         private Reference JavaDoc<ProxyResult<T>> result;
281         
282         public WeakResult(ProxyResult<T> r, Lookup.Result<T> s) {
283             this.result = new WeakReference JavaDoc<ProxyResult<T>>(r);
284             this.source = s;
285         }
286         
287         protected void beforeLookup(Lookup.Template t) {
288             ProxyResult r = (ProxyResult)result.get();
289             if (r != null) {
290                 r.beforeLookup(t);
291             } else {
292                 source.removeLookupListener(this);
293             }
294         }
295
296         protected void collectFires(Collection<Object JavaDoc> evAndListeners) {
297             ProxyResult<T> r = result.get();
298             if (r != null) {
299                 r.collectFires(evAndListeners);
300             } else {
301                 source.removeLookupListener(this);
302             }
303         }
304
305         public void addLookupListener(LookupListener l) {
306             assert false;
307         }
308
309         public void removeLookupListener(LookupListener l) {
310             assert false;
311         }
312
313         public Collection<T> allInstances() {
314             assert false;
315             return null;
316         }
317
318         public void resultChanged(LookupEvent ev) {
319             ProxyResult r = (ProxyResult)result.get();
320             if (r != null) {
321                 r.resultChanged(ev);
322             } else {
323                 source.removeLookupListener(this);
324             }
325         }
326
327         public Collection<? extends Item<T>> allItems() {
328             assert false;
329             return null;
330         }
331
332         public Set<Class JavaDoc<? extends T>> allClasses() {
333             assert false;
334             return null;
335         }
336     } // end of WeakResult
337
}
338
Popular Tags