|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.util; import java.util.*; import org.openide.util.lookup.Lookups; import org.openide.util.lookup.ProxyLookup; /** * A general registry permitting clients to find instances of services * (implementation of a given interface). * This class is inspired by the * Jini * registration and lookup mechanism. The difference is that the methods do * not throw checked exceptions (as they usually work only locally and not over the network) * and that the Lookup API concentrates on the lookup, not on the registration * (although {Lookup#getDefault} is strongly encouraged to support * {@link Lookups#metaInfServices} for registration in addition to whatever * else it decides to support). *
metaInfServices
* implementation in the returned lookup as usage of META-INF/services
* is a JDK standard.
*
* @return the global lookup in the system
*/
public static synchronized Lookup getDefault() {
if (defaultLookup != null) {
return defaultLookup;
}
// You can specify a Lookup impl using a system property if you like.
String className = System.getProperty(
"org.openide.util.Lookup" // NOI18N
);
if ("-".equals(className)) { // NOI18N
// Suppress even MetaInfServicesLookup.
return EMPTY;
}
ClassLoader l = Thread.currentThread().getContextClassLoader();
try {
if (className != null) {
defaultLookup = (Lookup)Class.forName(className, true, l).newInstance();
return defaultLookup;
}
} catch (Exception e) {
// do not use ErrorManager because we are in the startup code
// and ErrorManager might not be ready
e.printStackTrace();
}
// OK, none specified (successfully) in a system property.
// Try MetaInfServicesLookup as a default, which may also
// have a org.openide.util.Lookup line specifying the lookup.
Lookup misl = Lookups.metaInfServices(l);
defaultLookup = (Lookup)misl.lookup(Lookup.class);
if (defaultLookup != null) {
return defaultLookup;
}
// You may also specify a Lookup.Provider.
Lookup.Provider prov = (Lookup.Provider)misl.lookup(Lookup.Provider.class);
if (prov != null) {
defaultLookup = Lookups.proxy(prov);
return defaultLookup;
}
// Had no such line, use simple impl.
// It does however need to have ClassLoader available or many things will break.
// Use the thread context classloader in effect now.
Lookup clLookup = Lookups.singleton(l);
defaultLookup = new ProxyLookup(new Lookup[] {misl, clLookup});
return defaultLookup;
}
/** Empty constructor for use by subclasses. */
public Lookup() {}
/** Look up an object matching a given interface.
* This is the simplest method to use.
* If more than one object matches, one will be returned arbitrarily.
* The template class may be a class or interface; the instance is
* guaranteed to be assignable to it.
*
* @param clazz class of the object we are searching for
* @return an object implementing the given class or null if no such
* implementation is found
*/
public abstract Object lookup (Class clazz);
/** The general lookup method. Callers can get list of all instances and classes
* that match the given template , request more info about
* them in form of {@link Lookup.Item} and attach a listener to
* this be notified about changes. The general interface does not
* specify whether subsequent calls with the same template produce new
* instance of the {@link Lookup.Result} or return shared instance. The
* prefered behaviour however is to return shared one.
*
* @param template a template describing the services to look for
* @return an object containing the results
*/
public abstract Result lookup (Template template);
/** Look up the first item matching a given template.
* Includes not only the instance but other associated information.
* @param template the template to check
* @return a matching item or null
*
* @since 1.8
*/
public Item lookupItem (Template template) {
Result res = lookup (template);
Iterator it = res.allItems ().iterator ();
return it.hasNext () ? (Item)it.next () : null;
}
/*
* I expect this class to grow in the future, but for now, it is
* enough to start with something simple.
*/
/** Template defining a pattern to filter instances by.
*/
public static final class Template extends Object {
/** cached hash code */
private int hashCode;
/** type of the service */
private Class type;
/** identity to search for */
private String id;
/** instance to search for */
private Object instance;
/** General template to find all possible instances.
* @deprecated Use new Template (Object.class) which
* is going to be better typed with JDK1.5 templates and should produce
* the same result.
*/
public Template () {
this (null);
}
/** Create a simple template matching by class.
* @param type the class of service we are looking for (subclasses will match)
*/
public Template (Class type) {
this (type, null, null);
}
/** Constructor to create new template.
* @param type the class of service we are looking for or null to leave unspecified
* @param id the ID of the item/service we are looking for or null to leave unspecified
* @param instance a specific known instance to look for or null to leave unspecified
*/
public Template (Class type, String id, Object instance) {
this.type = type == null ? Object.class : type;
this.id = id;
this.instance = instance;
}
/** Get the class (or superclass or interface) to search for.
* If it was not specified in the constructor, Object is used as
* this will match any instance.
* @return the class to search for
*/
public Class getType () {
return type;
}
/** Get the persistent identifier being searched for, if any.
* @return the ID or null
* @see Lookup.Item#getId
*
* @since 1.8
*/
public String getId () {
return id;
}
/** Get the specific instance being searched for, if any.
* Most useful for finding an Item when the instance
* is already known.
*
* @return the object to find or null
*
* @since 1.8
*/
public Object getInstance () {
return instance;
}
/* Computes hashcode for this template. The hashcode is cached.
* @return hashcode
*/
public int hashCode () {
if (hashCode != 0) {
return hashCode;
}
hashCode =
(type == null ? 1 : type.hashCode ()) +
(id == null ? 2 : id.hashCode ()) +
(instance == null ? 3 : 0);
return hashCode;
}
/* Checks whether two templates represent the same query.
* @param obj another template to check
* @return true if so, false otherwise
*/
public boolean equals (Object obj) {
if (! (obj instanceof Template)) {
return false;
}
Template t = (Template)obj;
if (hashCode() != t.hashCode()) {
// this is an optimalization - the hashCodes should have been
// precomputed
return false;
}
if (type != t.type) {
return false;
}
if (id == null) {
if (t.id != null) {
return false;
}
} else {
if (! id.equals(t.id)) {
return false;
}
}
if (instance == null) {
return (t.instance == null);
} else {
return instance.equals(t.instance);
}
}
/* for debugging */
public String toString() {
return "Lookup.Template[type=" + type + ",id=" + id + ",instance=" + instance + "]"; // NOI18N
}
}
/** Result of a lookup request.
* Allows access to all matching instances at once.
* Also permits listening to changes in the result.
* Result can contain duplicate items.
*/
public static abstract class Result extends Object {
/** Registers a listener that is invoked when there is a possible
* change in this result.
*
* @param l the listener to add
*/
public abstract void addLookupListener (LookupListener l);
/** Unregisters a listener previously added.
* @param l the listener to remove
*/
public abstract void removeLookupListener (LookupListener l);
/** Get all instances in the result. The return value type
* should be List instead of Collection, but it is too late to change it.
* @return unmodifiable collection of all instances that will never change its content
*/
public abstract java.util.Collection allInstances ();
/** Get all classes represented in the result.
* That is, the set of concrete classes
* used by instances present in the result.
* All duplicate classes will be omitted.
* @return unmodifiable set of Class objects that will never change its content
*
* @since 1.8
*/
public java.util.Set allClasses () {
return java.util.Collections.EMPTY_SET;
}
/** Get all registered items.
* This should include all pairs of instances together
* with their classes, IDs, and so on. The return value type
* should be List instead of Collection, but it is too late to change it.
* @return unmodifiable collection of {@link Lookup.Item} that will never change its content
*
* @since 1.8
*/
public java.util.Collection allItems () {
return java.util.Collections.EMPTY_SET;
}
}
/** A single item in a lookup result.
* This wrapper provides unified access to not just the instance,
* but its class, a possible persistent identifier, and so on.
*
* @since 1.25
*/
public static abstract class Item extends Object {
/** Get the instance itself.
* @return the instance or null if the instance cannot be created
*/
public abstract Object getInstance ();
/** Get the implementing class of the instance.
* @return the class of the item
*/
public abstract Class getType ();
// XXX can it be null??
/** Get a persistent indentifier for the item.
* This identifier should uniquely represent the item
* within its containing lookup (and if possible within the
* global lookup as a whole). For example, it might represent
* the source of the instance as a file name. The ID may be
* persisted and in a later session used to find the same instance
* as was encountered earlier, by means of passing it into a
* lookup template.
*
* @return a string ID of the item
*/
public abstract String getId ();
/** Get a human presentable name for the item.
* This might be used when summarizing all the items found in a
* lookup result in some part of a GUI.
* @return the string suitable for presenting the object to a user
*/
public abstract String getDisplayName ();
/* show ID for debugging */
public String toString () {
return getId ();
}
}
/**
* Objects implementing interface Lookup.Provider are capable of
* and willing to provide a lookup (usually bound to the object).
* @since 3.6
*/
public interface Provider {
/**
* Returns lookup associated with the object.
* @return fully initialized lookup instance provided by this object
*/
Lookup getLookup();
}
//
// Implementation of the default lookup
//
private static final class Empty extends Lookup {
Empty() {}
private static final Result NO_RESULT = new Result () {
/** Registers a listener that is invoked when there is a possible
* change in this result.
*
* @param l listener to invoke when there is an change
*/
public void addLookupListener (LookupListener l) {
}
/** Unregisters a listener previously added by addChangeListener.
* @param l the listener
*/
public void removeLookupListener (LookupListener l) {
}
/** Access to all instances in the result.
* @return collection of all instances
*/
public java.util.Collection allInstances () {
return java.util.Collections.EMPTY_SET;
}
};
/** Lookups an object of given interface. This is the simplest method
* for the lookuping, if more registered objects implement the given
* class any of them can be returned.
*
* @param clazz class of the object we are searching for
* @return the object implementing given class or null if no such
* has been found
*/
public Object lookup(Class clazz) {
return null;
}
/** The general lookup method.
* @param template the template describing the services we are looking for
* @return object containing the results
*/
public Result lookup(Template template) {
return NO_RESULT;
}
}
}
|
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.