lookup/src/main/java/org/openide/util/lookup/SimpleProxyLookup.java
changeset 972 a2947558c966
parent 971 b3ae88304dd0
child 973 5653a70ebb56
     1.1 --- a/lookup/src/main/java/org/openide/util/lookup/SimpleProxyLookup.java	Wed Jan 27 17:46:23 2010 -0500
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,359 +0,0 @@
     1.4 -/*
     1.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.6 - *
     1.7 - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
     1.8 - *
     1.9 - * The contents of this file are subject to the terms of either the GNU
    1.10 - * General Public License Version 2 only ("GPL") or the Common
    1.11 - * Development and Distribution License("CDDL") (collectively, the
    1.12 - * "License"). You may not use this file except in compliance with the
    1.13 - * License. You can obtain a copy of the License at
    1.14 - * http://www.netbeans.org/cddl-gplv2.html
    1.15 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    1.16 - * specific language governing permissions and limitations under the
    1.17 - * License.  When distributing the software, include this License Header
    1.18 - * Notice in each file and include the License file at
    1.19 - * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
    1.20 - * particular file as subject to the "Classpath" exception as provided
    1.21 - * by Sun in the GPL Version 2 section of the License file that
    1.22 - * accompanied this code. If applicable, add the following below the
    1.23 - * License Header, with the fields enclosed by brackets [] replaced by
    1.24 - * your own identifying information:
    1.25 - * "Portions Copyrighted [year] [name of copyright owner]"
    1.26 - *
    1.27 - * Contributor(s):
    1.28 - *
    1.29 - * The Original Software is NetBeans. The Initial Developer of the Original
    1.30 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
    1.31 - * Microsystems, Inc. All Rights Reserved.
    1.32 - *
    1.33 - * If you wish your version of this file to be governed by only the CDDL
    1.34 - * or only the GPL Version 2, indicate your decision by adding
    1.35 - * "[Contributor] elects to include this software in this distribution
    1.36 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
    1.37 - * single choice of license, a recipient has the option to distribute
    1.38 - * your version of this file under either the CDDL, the GPL Version 2 or
    1.39 - * to extend the choice of license to its licensees as provided above.
    1.40 - * However, if you add GPL Version 2 code and therefore, elected the GPL
    1.41 - * Version 2 license, then the option applies only if the new code is
    1.42 - * made subject to such option by the copyright holder.
    1.43 - */
    1.44 -package org.openide.util.lookup;
    1.45 -
    1.46 -import java.lang.ref.Reference;
    1.47 -import java.lang.ref.WeakReference;
    1.48 -import org.openide.util.Lookup;
    1.49 -import org.openide.util.LookupEvent;
    1.50 -import org.openide.util.LookupListener;
    1.51 -
    1.52 -import java.util.*;
    1.53 -
    1.54 -
    1.55 -/**
    1.56 - * Simple proxy lookup. Keeps reference to a lookup it delegates to and
    1.57 - * forwards all requests.
    1.58 - *
    1.59 - * @author Jaroslav Tulach
    1.60 - */
    1.61 -final class SimpleProxyLookup extends org.openide.util.Lookup {
    1.62 -    /** the provider to check for the status */
    1.63 -    private Provider provider;
    1.64 -
    1.65 -    /** the lookup we currently delegate to */
    1.66 -    private Lookup delegate;
    1.67 -
    1.68 -    /** map of all templates to Reference (results) associated to this lookup */
    1.69 -    private WeakHashMap<Template<?>,Reference<ProxyResult<?>>> results;
    1.70 -
    1.71 -    /**
    1.72 -     * @param provider provider to delegate to
    1.73 -     */
    1.74 -    SimpleProxyLookup(Provider provider) {
    1.75 -        this.provider = provider;
    1.76 -    }
    1.77 -
    1.78 -    /** Checks whether we still delegate to the same lookup */
    1.79 -    private Lookup checkLookup() {
    1.80 -        Lookup l = provider.getLookup();
    1.81 -
    1.82 -        // iterator over Reference (ProxyResult)
    1.83 -        Iterator<Reference<ProxyResult<?>>> toCheck = null;
    1.84 -
    1.85 -        synchronized (this) {
    1.86 -            if (l != delegate) {
    1.87 -                this.delegate = l;
    1.88 -
    1.89 -                if (results != null) {
    1.90 -                    toCheck = new ArrayList<Reference<ProxyResult<?>>>(results.values()).iterator();
    1.91 -                }
    1.92 -            }
    1.93 -        }
    1.94 -
    1.95 -        if (toCheck != null) {
    1.96 -            // update
    1.97 -            ArrayList<Object> evAndListeners = new ArrayList<Object>();
    1.98 -            for (Iterator<Reference<ProxyResult<?>>> it = toCheck; it.hasNext(); ) {
    1.99 -                java.lang.ref.Reference<ProxyResult<?>> ref = it.next();
   1.100 -                if (ref == null) {
   1.101 -                    continue;
   1.102 -                }
   1.103 -
   1.104 -                ProxyResult<?> p = ref.get();
   1.105 -
   1.106 -                if (p != null && p.updateLookup(l)) {
   1.107 -                    p.collectFires(evAndListeners);
   1.108 -                }
   1.109 -            }
   1.110 -            
   1.111 -            for (Iterator it = evAndListeners.iterator(); it.hasNext(); ) {
   1.112 -                LookupEvent ev = (LookupEvent)it.next();
   1.113 -                LookupListener ll = (LookupListener)it.next();
   1.114 -                ll.resultChanged(ev);
   1.115 -            }
   1.116 -        }
   1.117 -
   1.118 -        return delegate;
   1.119 -    }
   1.120 -
   1.121 -    @SuppressWarnings("unchecked")
   1.122 -    private static <T> ProxyResult<T> cast(ProxyResult<?> p) {
   1.123 -        return (ProxyResult<T>)p;
   1.124 -    }
   1.125 -
   1.126 -    public <T> Result<T> lookup(Template<T> template) {
   1.127 -        synchronized (this) {
   1.128 -            if (results == null) {
   1.129 -                results = new WeakHashMap<Template<?>,Reference<ProxyResult<?>>>();
   1.130 -            } else {
   1.131 -                Reference<ProxyResult<?>> ref = results.get(template);
   1.132 -
   1.133 -                if (ref != null) {
   1.134 -                    ProxyResult<?> p = ref.get();
   1.135 -
   1.136 -                    if (p != null) {
   1.137 -                        return cast(p);
   1.138 -                    }
   1.139 -                }
   1.140 -            }
   1.141 -
   1.142 -            ProxyResult<T> p = new ProxyResult<T>(template);
   1.143 -            Reference<ProxyResult<?>> ref = new WeakReference<ProxyResult<?>>(p);
   1.144 -            results.put(template, ref);
   1.145 -
   1.146 -            return p;
   1.147 -        }
   1.148 -    }
   1.149 -
   1.150 -    public <T> T lookup(Class<T> clazz) {
   1.151 -        if (clazz == null) {
   1.152 -            checkLookup();
   1.153 -            return null;
   1.154 -        }
   1.155 -        return checkLookup().lookup(clazz);
   1.156 -    }
   1.157 -
   1.158 -    public <T> Item<T> lookupItem(Template<T> template) {
   1.159 -        return checkLookup().lookupItem(template);
   1.160 -    }
   1.161 -
   1.162 -    /**
   1.163 -     * Result used in SimpleLookup. It holds a reference to the collection
   1.164 -     * passed in constructor. As the contents of this lookup result never
   1.165 -     * changes the addLookupListener and removeLookupListener are empty.
   1.166 -     */
   1.167 -    private final class ProxyResult<T> extends WaitableResult<T> implements LookupListener {
   1.168 -        /** Template used for this result. It is never null.*/
   1.169 -        private Template<T> template;
   1.170 -
   1.171 -        /** result to delegate to */
   1.172 -        private Lookup.Result<T> delegate;
   1.173 -
   1.174 -        /** listeners set */
   1.175 -        private javax.swing.event.EventListenerList listeners;
   1.176 -        private LookupListener lastListener;
   1.177 -
   1.178 -        /** Just remembers the supplied argument in variable template.*/
   1.179 -        ProxyResult(Template<T> template) {
   1.180 -            this.template = template;
   1.181 -        }
   1.182 -
   1.183 -        /** Checks state of the result
   1.184 -         */
   1.185 -        private Result<T> checkResult() {
   1.186 -            updateLookup(checkLookup());
   1.187 -
   1.188 -            return this.delegate;
   1.189 -        }
   1.190 -
   1.191 -        /** Updates the state of the lookup.
   1.192 -         * @return true if the lookup really changed
   1.193 -         */
   1.194 -        public boolean updateLookup(Lookup l) {
   1.195 -            Collection<? extends Item<T>> oldPairs = (delegate != null) ? delegate.allItems() : null;
   1.196 -
   1.197 -            LookupListener removedListener;
   1.198 -
   1.199 -            synchronized (this) {
   1.200 -                if ((delegate != null) && (lastListener != null)) {
   1.201 -                    removedListener = lastListener;
   1.202 -                    delegate.removeLookupListener(lastListener);
   1.203 -                } else {
   1.204 -                    removedListener = null;
   1.205 -                }
   1.206 -            }
   1.207 -
   1.208 -            // cannot call to foreign code 
   1.209 -            Lookup.Result<T> res = l.lookup(template);
   1.210 -
   1.211 -            synchronized (this) {
   1.212 -                if (removedListener == lastListener) {
   1.213 -                    delegate = res;
   1.214 -                    lastListener = new WeakResult<T>(this, delegate);
   1.215 -                    delegate.addLookupListener(lastListener);
   1.216 -                }
   1.217 -            }
   1.218 -
   1.219 -            if (oldPairs == null) {
   1.220 -                // nobody knows about a change
   1.221 -                return false;
   1.222 -            }
   1.223 -
   1.224 -            Collection<? extends Item<T>> newPairs = delegate.allItems();
   1.225 -
   1.226 -            // See #34961 for explanation.
   1.227 -            if (!(oldPairs instanceof List)) {
   1.228 -                if (oldPairs == Collections.EMPTY_SET) {
   1.229 -                    // avoid allocation
   1.230 -                    oldPairs = Collections.emptyList();
   1.231 -                } else {
   1.232 -                    oldPairs = new ArrayList<Item<T>>(oldPairs);
   1.233 -                }
   1.234 -            }
   1.235 -
   1.236 -            if (!(newPairs instanceof List)) {
   1.237 -                newPairs = new ArrayList<Item<T>>(newPairs);
   1.238 -            }
   1.239 -
   1.240 -            return !oldPairs.equals(newPairs);
   1.241 -        }
   1.242 -
   1.243 -        public synchronized void addLookupListener(LookupListener l) {
   1.244 -            if (listeners == null) {
   1.245 -                listeners = new javax.swing.event.EventListenerList();
   1.246 -            }
   1.247 -
   1.248 -            listeners.add(LookupListener.class, l);
   1.249 -        }
   1.250 -
   1.251 -        public synchronized void removeLookupListener(LookupListener l) {
   1.252 -            if (listeners != null) {
   1.253 -                listeners.remove(LookupListener.class, l);
   1.254 -            }
   1.255 -        }
   1.256 -
   1.257 -        public java.util.Collection<? extends T> allInstances() {
   1.258 -            return checkResult().allInstances();
   1.259 -        }
   1.260 -
   1.261 -        public Set<Class<? extends T>> allClasses() {
   1.262 -            return checkResult().allClasses();
   1.263 -        }
   1.264 -
   1.265 -        public Collection<? extends Item<T>> allItems() {
   1.266 -            return checkResult().allItems();
   1.267 -        }
   1.268 -
   1.269 -        protected void beforeLookup(Lookup.Template t) {
   1.270 -            Lookup.Result r = checkResult();
   1.271 -
   1.272 -            if (r instanceof WaitableResult) {
   1.273 -                ((WaitableResult) r).beforeLookup(t);
   1.274 -            }
   1.275 -        }
   1.276 -
   1.277 -        /** A change in lookup occured.
   1.278 -         * @param ev event describing the change
   1.279 -         *
   1.280 -         */
   1.281 -        public void resultChanged(LookupEvent anEvent) {
   1.282 -            collectFires(null);
   1.283 -        } 
   1.284 -        
   1.285 -        protected void collectFires(Collection<Object> evAndListeners) {
   1.286 -            javax.swing.event.EventListenerList l = this.listeners;
   1.287 -
   1.288 -            if (l == null) {
   1.289 -                return;
   1.290 -            }
   1.291 -
   1.292 -            Object[] listeners = l.getListenerList();
   1.293 -
   1.294 -            if (listeners.length == 0) {
   1.295 -                return;
   1.296 -            }
   1.297 -
   1.298 -            LookupEvent ev = new LookupEvent(this);
   1.299 -            AbstractLookup.notifyListeners(listeners, ev, evAndListeners);
   1.300 -        }
   1.301 -    }
   1.302 -     // end of ProxyResult
   1.303 -    private final class WeakResult<T> extends WaitableResult<T> implements LookupListener {
   1.304 -        private Lookup.Result source;
   1.305 -        private Reference<ProxyResult<T>> result;
   1.306 -        
   1.307 -        public WeakResult(ProxyResult<T> r, Lookup.Result<T> s) {
   1.308 -            this.result = new WeakReference<ProxyResult<T>>(r);
   1.309 -            this.source = s;
   1.310 -        }
   1.311 -        
   1.312 -        protected void beforeLookup(Lookup.Template t) {
   1.313 -            ProxyResult r = (ProxyResult)result.get();
   1.314 -            if (r != null) {
   1.315 -                r.beforeLookup(t);
   1.316 -            } else {
   1.317 -                source.removeLookupListener(this);
   1.318 -            }
   1.319 -        }
   1.320 -
   1.321 -        protected void collectFires(Collection<Object> evAndListeners) {
   1.322 -            ProxyResult<T> r = result.get();
   1.323 -            if (r != null) {
   1.324 -                r.collectFires(evAndListeners);
   1.325 -            } else {
   1.326 -                source.removeLookupListener(this);
   1.327 -            }
   1.328 -        }
   1.329 -
   1.330 -        public void addLookupListener(LookupListener l) {
   1.331 -            assert false;
   1.332 -        }
   1.333 -
   1.334 -        public void removeLookupListener(LookupListener l) {
   1.335 -            assert false;
   1.336 -        }
   1.337 -
   1.338 -        public Collection<T> allInstances() {
   1.339 -            assert false;
   1.340 -            return null;
   1.341 -        }
   1.342 -
   1.343 -        public void resultChanged(LookupEvent ev) {
   1.344 -            ProxyResult r = (ProxyResult)result.get();
   1.345 -            if (r != null) {
   1.346 -                r.resultChanged(ev);
   1.347 -            } else {
   1.348 -                source.removeLookupListener(this);
   1.349 -            }
   1.350 -        }
   1.351 -
   1.352 -        public Collection<? extends Item<T>> allItems() {
   1.353 -            assert false;
   1.354 -            return null;
   1.355 -        }
   1.356 -
   1.357 -        public Set<Class<? extends T>> allClasses() {
   1.358 -            assert false;
   1.359 -            return null;
   1.360 -        }
   1.361 -    } // end of WeakResult
   1.362 -}