org.openide.util.lookup.Lookups Maven / Gradle / Ivy
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.openide.util.lookup; import java.util.Arrays; import org.netbeans.modules.openide.util.GlobalLookup; import org.openide.util.Lookup; import org.openide.util.lookup.implspi.NamedServicesProvider; /** * Static factory methods for creating common lookup implementations. * * @author David Strupl * @since 2.21 */ public class Lookups { /** static methods only */ private Lookups() {} /** * Creates a singleton lookup. It means lookup that contains only * one object specified via the supplied parameter. The lookup will * either return the object or null if the supplied template does * not match the class. If the specified argument is null the method * will end with NullPointerException. * @return Fully initialized lookup object ready to use * @throws NullPointerException if the supplied argument is null * @since 2.21 */ public static Lookup singleton(Object objectToLookup) { if (objectToLookup == null) { throw new NullPointerException(); } return new SingletonLookup(objectToLookup); } /** * Creates a lookup that contains an array of objects specified via the * parameter. The resulting lookup is fixed in the following sense: it * contains only fixed set of objects passed in by the array parameter. * Its contents never changes so registering listeners on such lookup * does not have any observable effect (the listeners are never called). * * @param objectsToLookup list of objects to include * @return Fully initialized lookup object ready to use * @throws NullPointerException if the supplied argument is null * @since 2.21 * */ public static Lookup fixed(Object... objectsToLookup) { if (objectsToLookup == null) { throw new NullPointerException(); } if (objectsToLookup.length == 0) { return Lookup.EMPTY; } if (objectsToLookup.length == 1) { return singleton(objectsToLookup[0]); } return new SimpleLookup(Arrays.asList(objectsToLookup)); } /** * Creates a lookup that contains an array of objects specified via the * parameter. The resulting lookup is fixed in the following sense: it * contains only fixed set of objects passed in by the array parameter. * The objects returned from this lookup are converted to real objects * before they are returned by the lookup. * Its contents never changes so registering listeners on such lookup * does not have any observable effect (the listeners are never called). * * @return Fully initialized lookup object ready to use * @throws NullPointerException if the any of the arguments is null * @since 2.21 * */ public static
. * * @param provider the provider that returns a lookup to delegate to * @return lookup delegating to the lookup returned by the provider * @since 3.9 */ public static Lookup proxy(Lookup.Provider provider) { return new SimpleProxyLookup(provider); } /** Returns a lookup that implements the JDK1.3 JAR services mechanism and delegates * to META-INF/services/name.of.class files. *Lookup fixed(T[] keys, InstanceContent.Convertor super T,R> convertor) { if (keys == null) { throw new NullPointerException(); } if (convertor == null) { throw new NullPointerException(); } return new SimpleLookup(Arrays.asList(keys), convertor); } /** Creates a lookup that delegates to another one but that one can change * from time to time. The returned lookup checks every time somebody calls * lookup
orlookupItem
method whether the * provider still returns the same lookup. If not, it updates state of * all {@link org.openide.util.Lookup.Result}s * that it created (and that still exists). ** The user of this method has to implement its provider's
getLookup
* method (must be thread safe and fast, will be called often and from any thread) * pass it to this method and use the returned lookup. Whenever the user * changes the return value from thegetLookup
method and wants * to notify listeners on the lookup about that it should trigger the event * firing, for example by callinglookup.lookup (Object.class)
* directly on the lookup returned by this method * that forces a check of the return value of {@link org.openide.util.Lookup.Provider#getLookup}Some extensions to the JAR services specification are implemented: *
*
*- An entry may be followed by a line of the form
#position=integer
* to specify ordering. (Smaller numbers first, entries with unspecified position last.) *- A line of the form
#-classname
suppresses an entry registered * in another file, so can be used to supersede one implementation with another. *Note: It is not dynamic - so if you need to change the classloader or JARs, * wrap it in a {@link ProxyLookup} and change the delegate when necessary. * Existing instances will be kept if the implementation classes are unchanged, * so there is "stability" in doing this provided some parent loaders are the same * as the previous ones. * @since 3.35 * @see ServiceProvider */ public static Lookup metaInfServices(ClassLoader classLoader) { return new MetaInfServicesLookup(classLoader, "META-INF/services/"); // NOI18N } /** Returns a lookup that behaves exactly like {@link #metaInfServices(ClassLoader)} * except that it does not read data from
META-INF/services/
, but instead * from the specified prefix. * @param classLoader class loader to use for loading * @param prefix prefix to prepend to the class name when searching * @since 7.9 * @see ServiceProvider#path */ public static Lookup metaInfServices(ClassLoader classLoader, String prefix) { return new MetaInfServicesLookup(classLoader, prefix); } /** Creates anamedlookup. * It is a lookup identified by a given path. * Two lookups with the same path should have the same content. *It is expected that each
namedlookup * will contain a superset of what would be created by: *{@linkplain #metaInfServices(ClassLoader,String) metaInfServices}(theRightLoader, "META-INF/namedservices/" + path + "/")
* *Various environments can add their own * extensions to its content. As such * {@link Lookups#forPath(java.lang.String)} can combine lookups * from several sources. In current NetBeans Runtime Container, two lookups are used: *
*
-
*
Lookups.metaInfServices("META-INF/namedservices/" + path)
* org.openide.loaders.FolderLookup(path)
*
* Please note that these lookups differ in the way they inspect sub-folders. * The first lookup just returns instances from the given path, ignoring * sub-folders, the second one retrieves instances from the whole sub-tree. *
*
* Read more about the usage of this method.
*
* @param path the path identifying the lookup, e.g. Servers/J2EEWrapper
* @return lookup associated with this path
* @since 7.9
* @see NamedServiceDefinition
*/
public static Lookup forPath(String path) {
if (!path.endsWith("/")) {
path = path + "/";
}
return NamedServicesProvider.forPath(path);
}
/** Creates a lookup that wraps another one and filters out instances
* of specified classes. If you have a lookup and
* you want to remove all instances of ActionMap you can use:
*
* l = Lookups.exclude(lookup, ActionMap.class); ** Then anybody who asks for
l.lookup(ActionMap.class)
or
* subclass will get null
. Even if the original lookup contains the
* value.
* To create empty lookup (well, just an example, otherwise use {@link Lookup#EMPTY}) one could use:
* * Lookup.exclude(anyLookup, Object.class); ** as any instance in any lookup is of type Object and thus would be excluded. *
* The complete behavior can be described as classes
being
* a barrier. For an object not to be excluded, there has to be an inheritance
* path between the queried class and the actual class of the instance,
* that is not blocked by any of the excluded classes and
* the queried class cannot be subclass of an excluded class:
*
* interface A {} * interface B {} * class C implements A, B {} * Object c = new C(); * Lookup l1 = Lookups.singleton(c); * Lookup l2 = Lookups.exclude(l1, A.class); * assertNull("A is directly excluded", l2.lookup(A.class)); * assertEquals("Returns C as A.class is not between B and C", c, l2.lookup(B.class)); ** For more info check the * * excluding lookup tests and the discussion in issue * 53058. * * @param lookup the original lookup that should be filtered * @param classes array of classes those instances should be excluded * @since 5.4 */ public static Lookup exclude(Lookup lookup, Class... classes) { return new ExcludingLookup(lookup, classes); } /** Creates
Lookup.Item
representing the instance passed in.
*
* @param instance the object for which Lookup.Item should be creted
* @param id unique identification of the object, for details see {@link org.openide.util.Lookup.Item#getId},
* can be null
* @return lookup item representing instance
* @since 4.8
*/
public static code
is running) changes value
* of {@link Lookup#getDefault()} to here-in provided lookup. Useful in a
* multi user environment where different users and their requests should
* be associated with different content of default lookup.
*
* As a special case, {@code executeWith} will execute the Runnable with
* the system global lookup (the one effective during system bootstrap), when
* the passed {@code defaultLookup} parameter is {@code null}. This feature may
* be useful to switch from a specialized Lookup back to a default one for
* some limited processing, or when the caller needs to bypass potential
* execution-local content temporary effective in the default Lookup and
* work with system-wide services only.
*
* @param defaultLookup the lookup to be come default while code is running
* @param code the code to execute (synchronously) before the method returns
* @since 8.30
* @since 8.31 can delegate to the system Lookup
*/
public static void executeWith(Lookup defaultLookup, Runnable code) {
if (!GlobalLookup.execute(defaultLookup, code)) {
code.run();
}
}
private static class LookupItem