lookup/src/main/java/org/openide/util/Lookup.java
changeset 972 a2947558c966
parent 971 b3ae88304dd0
child 973 5653a70ebb56
     1.1 --- a/lookup/src/main/java/org/openide/util/Lookup.java	Wed Jan 27 17:46:23 2010 -0500
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,544 +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 -
    1.45 -package org.openide.util;
    1.46 -
    1.47 -import java.util.ArrayList;
    1.48 -import java.util.Collection;
    1.49 -import java.util.Collections;
    1.50 -import java.util.Iterator;
    1.51 -import java.util.List;
    1.52 -import java.util.Set;
    1.53 -import org.openide.util.lookup.Lookups;
    1.54 -import org.openide.util.lookup.ProxyLookup;
    1.55 -import org.openide.util.lookup.ServiceProvider;
    1.56 -
    1.57 -/**
    1.58 - * A general registry permitting clients to find instances of services
    1.59 - * (implementation of a given interface).
    1.60 - * This class is inspired by the
    1.61 - * <a href="http://www.jini.org/">Jini</a>
    1.62 - * registration and lookup mechanism. The difference is that the methods do
    1.63 - * not throw checked exceptions (as they usually work only locally and not over the network)
    1.64 - * and that the Lookup API concentrates on the lookup, not on the registration
    1.65 - * (although {@link Lookup#getDefault} is strongly encouraged to support
    1.66 - * {@link Lookups#metaInfServices} for registration in addition to whatever
    1.67 - * else it decides to support).
    1.68 - * <p>
    1.69 - * For a general talk about the idea behind the lookup pattern please see
    1.70 - * <UL>
    1.71 - *      <LI><a href="lookup/doc-files/index.html">The Solution to Communication Between Components</a>
    1.72 - *      page
    1.73 - *      <LI>the introduction to the <a href="lookup/doc-files/lookup-api.html">lookup API via
    1.74 - *      use cases</a>
    1.75 - *      <LI>the examples of <a href="lookup/doc-files/lookup-spi.html">how to write your own lookup</a>
    1.76 - * </UL>
    1.77 - *
    1.78 - * @see org.openide.util.lookup.AbstractLookup
    1.79 - * @see Lookups
    1.80 - * @see LookupListener
    1.81 - * @see LookupEvent
    1.82 - * @author  Jaroslav Tulach
    1.83 - */
    1.84 -public abstract class Lookup {
    1.85 -    /** A dummy lookup that never returns any results.
    1.86 -     */
    1.87 -    public static final Lookup EMPTY = new Empty();
    1.88 -
    1.89 -    /** default instance */
    1.90 -    private static Lookup defaultLookup;
    1.91 -
    1.92 -    /** Empty constructor for use by subclasses. */
    1.93 -    public Lookup() {
    1.94 -    }
    1.95 -
    1.96 -    /** Static method to obtain the global lookup in the whole system.
    1.97 -     * The actual returned implementation can be different in different
    1.98 -     * systems, but the default one is based on
    1.99 -     * {@link org.openide.util.lookup.Lookups#metaInfServices}
   1.100 -     * with the context classloader of the first caller. Each system is
   1.101 -     * adviced to honor this and include some form of <code>metaInfServices</code>
   1.102 -     * implementation in the returned lookup as usage of <code>META-INF/services</code>
   1.103 -     * is a JDK standard.
   1.104 -     *
   1.105 -     * @return the global lookup in the system
   1.106 -     * @see ServiceProvider
   1.107 -     */
   1.108 -    public static synchronized Lookup getDefault() {
   1.109 -        if (defaultLookup != null) {
   1.110 -            return defaultLookup;
   1.111 -        }
   1.112 -
   1.113 -        // You can specify a Lookup impl using a system property if you like.
   1.114 -        String className = System.getProperty("org.openide.util.Lookup" // NOI18N
   1.115 -            );
   1.116 -
   1.117 -        if ("-".equals(className)) { // NOI18N
   1.118 -
   1.119 -            // Suppress even MetaInfServicesLookup.
   1.120 -            return EMPTY;
   1.121 -        }
   1.122 -
   1.123 -        ClassLoader l = Thread.currentThread().getContextClassLoader();
   1.124 -
   1.125 -        try {
   1.126 -            if (className != null) {
   1.127 -                defaultLookup = (Lookup) Class.forName(className, true, l).newInstance();
   1.128 -
   1.129 -                return defaultLookup;
   1.130 -            }
   1.131 -        } catch (Exception e) {
   1.132 -            // do not use ErrorManager because we are in the startup code
   1.133 -            // and ErrorManager might not be ready
   1.134 -            e.printStackTrace();
   1.135 -        }
   1.136 -
   1.137 -        // OK, none specified (successfully) in a system property.
   1.138 -        // Try MetaInfServicesLookup as a default, which may also
   1.139 -        // have a org.openide.util.Lookup line specifying the lookup.
   1.140 -        Lookup misl = Lookups.metaInfServices(l);
   1.141 -        defaultLookup = misl.lookup(Lookup.class);
   1.142 -
   1.143 -        if (defaultLookup != null) {
   1.144 -            return defaultLookup;
   1.145 -        }
   1.146 -
   1.147 -        // You may also specify a Lookup.Provider.
   1.148 -        Lookup.Provider prov = misl.lookup(Lookup.Provider.class);
   1.149 -
   1.150 -        if (prov != null) {
   1.151 -            defaultLookup = Lookups.proxy(prov);
   1.152 -
   1.153 -            return defaultLookup;
   1.154 -        }
   1.155 -
   1.156 -        DefLookup def = new DefLookup();
   1.157 -        def.init(l, misl, false);
   1.158 -        defaultLookup = def;
   1.159 -        def.init(l, misl, true);
   1.160 -        return defaultLookup;
   1.161 -    }
   1.162 -    
   1.163 -    private static final class DefLookup extends ProxyLookup {
   1.164 -        public DefLookup() {
   1.165 -            super(new Lookup[0]);
   1.166 -        }
   1.167 -        
   1.168 -        public void init(ClassLoader loader, Lookup metaInfLookup, boolean addPath) {
   1.169 -            // Had no such line, use simple impl.
   1.170 -            // It does however need to have ClassLoader available or many things will break.
   1.171 -            // Use the thread context classloader in effect now.
   1.172 -            Lookup clLookup = Lookups.singleton(loader);
   1.173 -            List<Lookup> arr = new ArrayList<Lookup>();
   1.174 -            arr.add(metaInfLookup);
   1.175 -            arr.add(clLookup);
   1.176 -            String paths = System.getProperty("org.openide.util.Lookup.paths"); // NOI18N
   1.177 -            if (addPath && paths != null) {
   1.178 -                for (String p : paths.split(":")) { // NOI18N
   1.179 -                    arr.add(Lookups.forPath(p));
   1.180 -                }
   1.181 -            }
   1.182 -            setLookups(arr.toArray(new Lookup[0]));
   1.183 -        }
   1.184 -    }
   1.185 -    
   1.186 -    /** Called from MockServices to reset default lookup in case services change
   1.187 -     */
   1.188 -    private static void resetDefaultLookup() {
   1.189 -        if (defaultLookup instanceof DefLookup) {
   1.190 -            DefLookup def = (DefLookup)defaultLookup;
   1.191 -            ClassLoader l = Thread.currentThread().getContextClassLoader();
   1.192 -            def.init(l, Lookups.metaInfServices(l), true);
   1.193 -        }
   1.194 -    }
   1.195 -
   1.196 -    /** Look up an object matching a given interface.
   1.197 -     * This is the simplest method to use.
   1.198 -     * If more than one object matches, the first will be returned.
   1.199 -     * The template class may be a class or interface; the instance is
   1.200 -     * guaranteed to be assignable to it.
   1.201 -     *
   1.202 -     * @param clazz class of the object we are searching for
   1.203 -     * @return an object implementing the given class or <code>null</code> if no such
   1.204 -     *         implementation is found
   1.205 -     */
   1.206 -    public abstract <T> T lookup(Class<T> clazz);
   1.207 -
   1.208 -    /** The general lookup method. Callers can get list of all instances and classes
   1.209 -     * that match the given <code>template</code>, request more info about
   1.210 -     * them in form of {@link Lookup.Item} and attach a listener to
   1.211 -     * this be notified about changes. The general interface does not
   1.212 -     * specify whether subsequent calls with the same template produce new
   1.213 -     * instance of the {@link Lookup.Result} or return shared instance. The
   1.214 -     * prefered behaviour however is to return shared one.
   1.215 -     *
   1.216 -     * @param template a template describing the services to look for
   1.217 -     * @return an object containing the results
   1.218 -     */
   1.219 -    public abstract <T> Result<T> lookup(Template<T> template);
   1.220 -
   1.221 -    /** Look up the first item matching a given template.
   1.222 -     * Includes not only the instance but other associated information.
   1.223 -     * @param template the template to check
   1.224 -     * @return a matching item or <code>null</code>
   1.225 -     *
   1.226 -     * @since 1.8
   1.227 -     */
   1.228 -    public <T> Item<T> lookupItem(Template<T> template) {
   1.229 -        Result<T> res = lookup(template);
   1.230 -        Iterator<? extends Item<T>> it = res.allItems().iterator();
   1.231 -        return it.hasNext() ? it.next() : null;
   1.232 -    }
   1.233 -
   1.234 -    /**
   1.235 -     * Find a result corresponding to a given class.
   1.236 -     * Equivalent to calling {@link #lookup(Lookup.Template)} but slightly more convenient.
   1.237 -     * Subclasses may override this method to produce the same semantics more efficiently.
   1.238 -     * @param clazz the supertype of the result
   1.239 -     * @return a live object representing instances of that type
   1.240 -     * @since org.openide.util 6.10
   1.241 -     */
   1.242 -    public <T> Lookup.Result<T> lookupResult(Class<T> clazz) {
   1.243 -        return lookup(new Lookup.Template<T>(clazz));
   1.244 -    }
   1.245 -
   1.246 -    /**
   1.247 -     * Find all instances corresponding to a given class.
   1.248 -     * Equivalent to calling {@link #lookupResult} and asking for {@link Lookup.Result#allInstances} but slightly more convenient.
   1.249 -     * Subclasses may override this method to produce the same semantics more efficiently.
   1.250 -     * <div class="nonnormative">
   1.251 -     * <p>Example usage:</p>
   1.252 -     * <pre>
   1.253 -     * for (MyService svc : Lookup.getDefault().lookupAll(MyService.class)) {
   1.254 -     *     svc.useMe();
   1.255 -     * }
   1.256 -     * </pre>
   1.257 -     * </div>
   1.258 -     * @param clazz the supertype of the result
   1.259 -     * @return all currently available instances of that type
   1.260 -     * @since org.openide.util 6.10
   1.261 -     */
   1.262 -    public <T> Collection<? extends T> lookupAll(Class<T> clazz) {
   1.263 -        return lookupResult(clazz).allInstances();
   1.264 -    }
   1.265 -
   1.266 -    /**
   1.267 -     * Objects implementing interface Lookup.Provider are capable of
   1.268 -     * and willing to provide a lookup (usually bound to the object).
   1.269 -     * @since 3.6
   1.270 -     */
   1.271 -    public interface Provider {
   1.272 -        /**
   1.273 -         * Returns lookup associated with the object.
   1.274 -         * @return fully initialized lookup instance provided by this object
   1.275 -         */
   1.276 -        Lookup getLookup();
   1.277 -    }
   1.278 -
   1.279 -    /*
   1.280 -     * I expect this class to grow in the future, but for now, it is
   1.281 -     * enough to start with something simple.
   1.282 -     */
   1.283 -
   1.284 -    /** Template defining a pattern to filter instances by.
   1.285 -     */
   1.286 -    public static final class Template<T> extends Object {
   1.287 -        /** cached hash code */
   1.288 -        private int hashCode;
   1.289 -
   1.290 -        /** type of the service */
   1.291 -        private Class<T> type;
   1.292 -
   1.293 -        /** identity to search for */
   1.294 -        private String id;
   1.295 -
   1.296 -        /** instance to search for */
   1.297 -        private T instance;
   1.298 -
   1.299 -        /** General template to find all possible instances.
   1.300 -         * @deprecated Use <code>new Template (Object.class)</code> which
   1.301 -         *   is going to be better typed with JDK1.5 templates and should produce
   1.302 -         *   the same result.
   1.303 -         */
   1.304 -        @Deprecated
   1.305 -        public Template() {
   1.306 -            this(null);
   1.307 -        }
   1.308 -
   1.309 -        /** Create a simple template matching by class.
   1.310 -         * @param type the class of service we are looking for (subclasses will match)
   1.311 -         */
   1.312 -        public Template(Class<T> type) {
   1.313 -            this(type, null, null);
   1.314 -        }
   1.315 -
   1.316 -        /** Constructor to create new template.
   1.317 -         * @param type the class of service we are looking for or <code>null</code> to leave unspecified
   1.318 -         * @param id the ID of the item/service we are looking for or <code>null</code> to leave unspecified
   1.319 -         * @param instance a specific known instance to look for or <code>null</code> to leave unspecified
   1.320 -         */
   1.321 -        public Template(Class<T> type, String id, T instance) {
   1.322 -            this.type = extractType(type);
   1.323 -            this.id = id;
   1.324 -            this.instance = instance;
   1.325 -        }
   1.326 -
   1.327 -        @SuppressWarnings("unchecked")
   1.328 -        private Class<T> extractType(Class<T> type) {
   1.329 -            return (type == null) ? (Class<T>)Object.class : type;
   1.330 -        }
   1.331 -
   1.332 -        /** Get the class (or superclass or interface) to search for.
   1.333 -         * If it was not specified in the constructor, <code>Object</code> is used as
   1.334 -         * this will match any instance.
   1.335 -         * @return the class to search for
   1.336 -         */
   1.337 -        public Class<T> getType() {
   1.338 -            return type;
   1.339 -        }
   1.340 -
   1.341 -        /** Get the persistent identifier being searched for, if any.
   1.342 -         * @return the ID or <code>null</code>
   1.343 -         * @see Lookup.Item#getId
   1.344 -         *
   1.345 -         * @since 1.8
   1.346 -         */
   1.347 -        public String getId() {
   1.348 -            return id;
   1.349 -        }
   1.350 -
   1.351 -        /** Get the specific instance being searched for, if any.
   1.352 -         * Most useful for finding an <code>Item</code> when the instance
   1.353 -         * is already known.
   1.354 -         *
   1.355 -         * @return the object to find or <code>null</code>
   1.356 -         *
   1.357 -         * @since 1.8
   1.358 -         */
   1.359 -        public T getInstance() {
   1.360 -            return instance;
   1.361 -        }
   1.362 -
   1.363 -        /* Computes hashcode for this template. The hashcode is cached.
   1.364 -         * @return hashcode
   1.365 -         */
   1.366 -        @Override
   1.367 -        public int hashCode() {
   1.368 -            if (hashCode != 0) {
   1.369 -                return hashCode;
   1.370 -            }
   1.371 -
   1.372 -            hashCode = ((type == null) ? 1 : type.hashCode()) + ((id == null) ? 2 : id.hashCode()) +
   1.373 -                ((instance == null) ? 3 : 0);
   1.374 -
   1.375 -            return hashCode;
   1.376 -        }
   1.377 -
   1.378 -        /* Checks whether two templates represent the same query.
   1.379 -         * @param obj another template to check
   1.380 -         * @return true if so, false otherwise
   1.381 -         */
   1.382 -        @Override
   1.383 -        public boolean equals(Object obj) {
   1.384 -            if (!(obj instanceof Template)) {
   1.385 -                return false;
   1.386 -            }
   1.387 -
   1.388 -            Template t = (Template) obj;
   1.389 -
   1.390 -            if (hashCode() != t.hashCode()) {
   1.391 -                // this is an optimalization - the hashCodes should have been
   1.392 -                // precomputed
   1.393 -                return false;
   1.394 -            }
   1.395 -
   1.396 -            if (type != t.type) {
   1.397 -                return false;
   1.398 -            }
   1.399 -
   1.400 -            if (id == null) {
   1.401 -                if (t.id != null) {
   1.402 -                    return false;
   1.403 -                }
   1.404 -            } else {
   1.405 -                if (!id.equals(t.id)) {
   1.406 -                    return false;
   1.407 -                }
   1.408 -            }
   1.409 -
   1.410 -            if (instance == null) {
   1.411 -                return (t.instance == null);
   1.412 -            } else {
   1.413 -                return instance.equals(t.instance);
   1.414 -            }
   1.415 -        }
   1.416 -
   1.417 -        /* for debugging */
   1.418 -        @Override
   1.419 -        public String toString() {
   1.420 -            return "Lookup.Template[type=" + type + ",id=" + id + ",instance=" + instance + "]"; // NOI18N
   1.421 -        }
   1.422 -    }
   1.423 -
   1.424 -    /** Result of a lookup request.
   1.425 -     * Allows access to all matching instances at once.
   1.426 -     * Also permits listening to changes in the result.
   1.427 -     * Result can contain duplicate items.
   1.428 -     */
   1.429 -    public static abstract class Result<T> extends Object {
   1.430 -        /** Registers a listener that is invoked when there is a possible
   1.431 -         * change in this result.
   1.432 -         *
   1.433 -         * @param l the listener to add
   1.434 -         */
   1.435 -        public abstract void addLookupListener(LookupListener l);
   1.436 -
   1.437 -        /** Unregisters a listener previously added.
   1.438 -         * @param l the listener to remove
   1.439 -         */
   1.440 -        public abstract void removeLookupListener(LookupListener l);
   1.441 -
   1.442 -        /** Get all instances in the result. The return value type
   1.443 -         * should be List instead of Collection, but it is too late to change it.
   1.444 -         * @return unmodifiable collection of all instances that will never change its content
   1.445 -         */
   1.446 -        public abstract Collection<? extends T> allInstances();
   1.447 -
   1.448 -        /** Get all classes represented in the result.
   1.449 -         * That is, the set of concrete classes
   1.450 -         * used by instances present in the result.
   1.451 -         * All duplicate classes will be omitted.
   1.452 -         * @return unmodifiable set of <code>Class</code> objects that will never change its content
   1.453 -         *
   1.454 -         * @since 1.8
   1.455 -         */
   1.456 -        public Set<Class<? extends T>> allClasses() {
   1.457 -            return Collections.emptySet();
   1.458 -        }
   1.459 -
   1.460 -        /** Get all registered items.
   1.461 -         * This should include all pairs of instances together
   1.462 -         * with their classes, IDs, and so on. The return value type
   1.463 -         * should be List instead of Collection, but it is too late to change it.
   1.464 -         * @return unmodifiable collection of {@link Lookup.Item} that will never change its content
   1.465 -         *
   1.466 -         * @since 1.8
   1.467 -         */
   1.468 -        public Collection<? extends Item<T>> allItems() {
   1.469 -            return Collections.emptyList();
   1.470 -        }
   1.471 -    }
   1.472 -
   1.473 -    /** A single item in a lookup result.
   1.474 -     * This wrapper provides unified access to not just the instance,
   1.475 -     * but its class, a possible persistent identifier, and so on.
   1.476 -     *
   1.477 -     * @since 1.25
   1.478 -     */
   1.479 -    public static abstract class Item<T> extends Object {
   1.480 -        /** Get the instance itself.
   1.481 -         * @return the instance or null if the instance cannot be created
   1.482 -         */
   1.483 -        public abstract T getInstance();
   1.484 -
   1.485 -        /** Get the implementing class of the instance.
   1.486 -         * @return the class of the item
   1.487 -         */
   1.488 -        public abstract Class<? extends T> getType();
   1.489 -
   1.490 -        // XXX can it be null??
   1.491 -
   1.492 -        /** Get a persistent indentifier for the item.
   1.493 -         * This identifier should uniquely represent the item
   1.494 -         * within its containing lookup (and if possible within the
   1.495 -         * global lookup as a whole). For example, it might represent
   1.496 -         * the source of the instance as a file name. The ID may be
   1.497 -         * persisted and in a later session used to find the same instance
   1.498 -         * as was encountered earlier, by means of passing it into a
   1.499 -         * lookup template.
   1.500 -         *
   1.501 -         * @return a string ID of the item
   1.502 -         */
   1.503 -        public abstract String getId();
   1.504 -
   1.505 -        /** Get a human presentable name for the item.
   1.506 -         * This might be used when summarizing all the items found in a
   1.507 -         * lookup result in some part of a GUI.
   1.508 -         * @return the string suitable for presenting the object to a user
   1.509 -         */
   1.510 -        public abstract String getDisplayName();
   1.511 -
   1.512 -        /* show ID for debugging */
   1.513 -        @Override
   1.514 -        public String toString() {
   1.515 -            return getId();
   1.516 -        }
   1.517 -    }
   1.518 -
   1.519 -    //
   1.520 -    // Implementation of the default lookup
   1.521 -    //
   1.522 -    private static final class Empty extends Lookup {
   1.523 -        private static final Result NO_RESULT = new Result() {
   1.524 -                public void addLookupListener(LookupListener l) {
   1.525 -                }
   1.526 -
   1.527 -                public void removeLookupListener(LookupListener l) {
   1.528 -                }
   1.529 -
   1.530 -                public Collection allInstances() {
   1.531 -                    return Collections.EMPTY_SET;
   1.532 -                }
   1.533 -            };
   1.534 -
   1.535 -        Empty() {
   1.536 -        }
   1.537 -
   1.538 -        public <T> T lookup(Class<T> clazz) {
   1.539 -            return null;
   1.540 -        }
   1.541 -
   1.542 -        @SuppressWarnings("unchecked")
   1.543 -        public <T> Result<T> lookup(Template<T> template) {
   1.544 -            return NO_RESULT;
   1.545 -        }
   1.546 -    }
   1.547 -}