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 -}