/* ServiceRegistry.java -- A simple registry for service providers.
   Copyright (C) 2004, 2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.imageio.spi;

import gnu.classpath.ServiceFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

/**
 * A registry for service providers.
 *
 * @since 1.4
 *
 * @author Michael Koch (konqueror@gmx.de)
 * @author Sascha Brawer (brawer@dandelis.ch)
 */
public class ServiceRegistry
{
  // Package-private to avoid a trampoline.
  /**
   * The service categories of this registry.
   *
   * <p>Note that we expect that only very few categories will
   * typically be used with a registry. The most common case will be
   * one, it seems unlikely that any registry would contain more than
   * five or six categories. Therefore, we intentionally avoid the
   * overhead of a HashMap.
   *
   * @see #providers
   */
  final Class[] categories;


  /**
   * The registered providers for each service category, indexed by
   * the same index as the {@link #categories} array. If no provider
   * is registered for a category, the array entry will be
   * <code>null</code>.
   *
   * <p>Note that we expect that only very few providers will
   * typically be registered for a category. The most common case will
   * be one or two. Therefore, we intentionally avoid the overhead of
   * a HashMap.
   */
  private final LinkedList[] providers;


  /**
   * The ordring constaints for each service category, indexed by the
   * same index as the {@link #categories} array. The constraints for
   * a service category are stored as a <code>Map&lt;Object,
   * Set&lt;Object&gt;&gt;</code>, where the Map&#x2019;s values are
   * those providers that need to come after the key.  If no
   * constraints are imposed on the providers of a category, the array
   * entry will be <code>null</code>. If no constraints have been set
   * whatsoever, <code>constraints</code> will be <code>null</code>.
   *
   * <p>Note that we expect that only very few constraints will
   * typically be imposed on a category. The most common case will
   * be zero.
   */
  private IdentityHashMap[] constraints;

  
  /**
   * Constructs a <code>ServiceRegistry</code> for the specified
   * service categories.
   * 
   * @param categories the categories to support
   *
   * @throws IllegalArgumentException if <code>categories</code> is
   * <code>null</code>, or if its {@link Iterator#next()} method
   * returns <code>null</code>.
   *
   * @throws ClassCastException if <code>categories</code> does not
   * iterate over instances of {@link java.lang.Class}.
   */
  public ServiceRegistry(Iterator categories)
  {
    ArrayList cats = new ArrayList(/* expected size */ 10);

    if (categories == null)
      throw new IllegalArgumentException();

    while (categories.hasNext())
      {
        Class cat = (Class) categories.next();
        if (cat == null)
          throw new IllegalArgumentException();
        cats.add(cat);
      }

    int numCats = cats.size();
    this.categories = (Class[]) cats.toArray(new Class[numCats]);
    this.providers = new LinkedList[numCats];
  }


  /**
   * Finds service providers that are implementing the specified
   * Service Provider Interface.
   *
   * <p><b>On-demand loading:</b> Loading and initializing service
   * providers is delayed as much as possible. The rationale is that
   * typical clients will iterate through the set of installed service
   * providers until one is found that matches some criteria (like
   * supported formats, or quality of service). In such scenarios, it
   * might make sense to install only the frequently needed service
   * providers on the local machine. More exotic providers can be put
   * onto a server; the server will only be contacted when no suitable
   * service could be found locally.</p>
   *
   * <p><b>Security considerations:</b> Any loaded service providers
   * are loaded through the specified ClassLoader, or the system
   * ClassLoader if <code>classLoader</code> is
   * <code>null</code>. When <code>lookupProviders</code> is called,
   * the current {@link java.security.AccessControlContext} gets
   * recorded. This captured security context will determine the
   * permissions when services get loaded via the <code>next()</code>
   * method of the returned <code>Iterator</code>.</p>
   *
   * @param spi the service provider interface which must be
   * implemented by any loaded service providers.
   *
   * @param loader the class loader that will be used to load the
   * service providers, or <code>null</code> for the system class
   * loader. For using the context class loader, see {@link
   * #lookupProviders(Class)}.
   *
   * @return an iterator over instances of <code>spi</code>.
   *
   * @throws IllegalArgumentException if <code>spi</code> is
   * <code>null</code>.
   */
  public static Iterator lookupProviders(Class spi,
                                         ClassLoader loader)
  {
    return ServiceFactory.lookupProviders(spi, loader);
  }


  /**
   * Finds service providers that are implementing the specified
   * Service Provider Interface, using the context class loader
   * for loading providers.
   *
   * @param spi the service provider interface which must be
   * implemented by any loaded service providers.
   *
   * @return an iterator over instances of <code>spi</code>.
   *
   * @throws IllegalArgumentException if <code>spi</code> is
   * <code>null</code>.
   *
   * @see #lookupProviders(Class, ClassLoader)
   */
  public static Iterator lookupProviders(Class spi)
  {
    return ServiceFactory.lookupProviders(spi);
  }


  /**
   * Returns an iterator over all service categories.
   *
   * @return an unmodifiable {@link
   * java.util.Iterator}&lt;{@link java.lang.Class}&gt;.
   */
  public Iterator getCategories()
  {
    return new Iterator()
      {
        int index = -1;

        public boolean hasNext()
        {
          return index < categories.length - 1;
        }

        public Object next()
        {
          if (!hasNext())
            throw new NoSuchElementException();

          return categories[++index];
        }

        public void remove()
        {
          throw new UnsupportedOperationException();
        }
      };
  }


  /**
   * Registers a provider for a service category which is specified by
   * the class-internal category ID.
   *
   * @param provider the service provider to be registered.
   *
   * @param cat the service category, which is identified by an index
   * into the {@link #categories} array.
   *
   * @return <code>true</code> if <code>provider</code> is the first
   * provider that gets registered for the specified service category;
   * <code>false</code> if other providers have already been
   * registered for the same servide category.
   *
   * @throws IllegalArgumentException if <code>provider</code> is
   * <code>null</code>.
   *
   * @throws ClassCastException if <code>provider</code> does not
   * implement the specified service provider interface.
   */
  private synchronized boolean registerServiceProvider(Object provider,
                                                       int cat)
  {
    LinkedList provs;
    boolean result;
    Class category;

    if (provider == null)
      throw new IllegalArgumentException();

    category = categories[cat];
    if (!category.isInstance(provider))
      throw new ClassCastException(category.getName());

    provs = providers[cat];
    if (provs == null)
    {
      result = true;
      provs = providers[cat] = new LinkedList();
    }
    else
      result = false;

    provs.add(provider);
    if (provider instanceof RegisterableService)
      ((RegisterableService) provider).onRegistration(this, category);

    return result;
  }


  /**
   * Registers a provider for the specified service category.
   *
   * <p>If <code>provider</code> implements the {@link
   * RegisterableService} interface, its {@link
   * RegisterableService#onRegistration onRegistration} method is
   * invoked in order to inform the provider about the addition to
   * this registry.
   *
   * @param provider the service provider to be registered.
   *
   * @param category the service category under which
   * <code>provider</code> shall be registered.
   *
   * @return <code>true</code> if <code>provider</code> is the first
   * provider that gets registered for the specified service category;
   * <code>false</code> if other providers have already been
   * registered for the same servide category.
   *
   * @throws IllegalArgumentException if <code>provider</code> is
   * <code>null</code>, or if <code>category</code> is not among the
   * categories passed to the {@linkplain #ServiceRegistry(Iterator)
   * constructor} of this ServiceRegistry.
   *
   * @throws ClassCastException if <code>provider</code> does not
   * implement <code>category</code>.
   */
  public synchronized boolean registerServiceProvider(Object provider,
                                                      Class category)
  {
    for (int i = 0; i < categories.length; i++)
      if (categories[i] == category)
        return registerServiceProvider(provider, i);
    throw new IllegalArgumentException();
  }


  /**
   * Registers a provider under all service categories it
   * implements.
   *
   * <p>If <code>provider</code> implements the {@link
   * RegisterableService} interface, its {@link
   * RegisterableService#onRegistration onRegistration} method is
   * invoked in order to inform the provider about the addition to
   * this registry. If <code>provider</code> implements several
   * service categories, <code>onRegistration</code> gets called
   * multiple times.
   *
   * @param provider the service provider to be registered.
   *
   * @throws IllegalArgumentException if <code>provider</code> is
   * <code>null</code>, or if <code>provider</code> does not implement
   * any of the service categories passed to the {@linkplain
   * #ServiceRegistry(Iterator) constructor} of this ServiceRegistry.
   */
  public synchronized void registerServiceProvider(Object provider)
  {
    boolean ok = false;

    if (provider == null)
      throw new IllegalArgumentException();

    for (int i = 0; i < categories.length; i++)
      if (categories[i].isInstance(provider))
        {
          ok = true;
          registerServiceProvider(provider, i);
        }

    if (!ok)
      throw new IllegalArgumentException();
  }


  /**
   * Registers a number of providers under all service categories they
   * implement.
   *
   * <p>If a provider implements the {@link RegisterableService}
   * interface, its {@link RegisterableService#onRegistration
   * onRegistration} method is invoked in order to inform the provider
   * about the addition to this registry. If <code>provider</code>
   * implements several service categories,
   * <code>onRegistration</code> gets called multiple times.
   *
   * @throws IllegalArgumentException if <code>providers</code> is
   * <code>null</code>, if any iterated provider is <code>null</code>,
   * or if some iterated provider does not implement any of the
   * service categories passed to the {@linkplain
   * #ServiceRegistry(Iterator) constructor} of this
   * <code>ServiceRegistry</code>.
   */
  public synchronized void registerServiceProviders(Iterator providers)
  {
    if (providers == null)
      throw new IllegalArgumentException();

    while (providers.hasNext())
      registerServiceProvider(providers.next());
  }


  /**
   * De-registers a provider for a service category which is specified
   * by the class-internal category ID.
   *
   * @param provider the service provider to be registered.
   *
   * @param cat the service category, which is identified by an index
   * into the {@link #categories} array.
   *
   * @return <code>true</code> if <code>provider</code> was previously
   * registered for the specified service category; <code>false</code>
   * if if the provider had not been registered.
   *
   * @throws IllegalArgumentException if <code>provider</code> is
   * <code>null</code>.
   *
   * @throws ClassCastException if <code>provider</code> does not
   * implement the specified service provider interface.
   */
  private synchronized boolean deregisterServiceProvider(Object provider,
                                                         int cat)
  {
    LinkedList provs;
    boolean result;
    Class category;

    if (provider == null)
      throw new IllegalArgumentException();

    category = categories[cat];
    if (!category.isInstance(provider))
      throw new ClassCastException(category.getName());

    provs = providers[cat];
    if (provs == null)
      return false;

    result = provs.remove(provider);
    if (provs.isEmpty())
      providers[cat] = null;

    if (result && (provider instanceof RegisterableService))
      ((RegisterableService) provider).onDeregistration(this, category);

    return result;
  }


  /**
   * De-registers a provider for the specified service category.
   *
   * <p>If <code>provider</code> implements the {@link
   * RegisterableService} interface, its {@link
   * RegisterableService#onDeregistration onDeregistration} method is
   * invoked in order to inform the provider about the removal from
   * this registry.
   *
   * @param provider the service provider to be de-registered.
   *
   * @param category the service category from which
   * <code>provider</code> shall be de-registered.
   *
   * @return <code>true</code> if <code>provider</code> was previously
   * registered for the specified service category; <code>false</code>
   * if if the provider had not been registered.
   *
   * @throws IllegalArgumentException if <code>provider</code> is
   * <code>null</code>, or if <code>category</code> is not among the
   * categories passed to the {@linkplain #ServiceRegistry(Iterator)
   * constructor} of this ServiceRegistry.
   *
   * @throws ClassCastException if <code>provider</code> does not
   * implement <code>category</code>.
   */
  public synchronized boolean deregisterServiceProvider(Object provider,
                                                        Class category)
  {
    for (int i = 0; i < categories.length; i++)
      if (categories[i] == category)
        return deregisterServiceProvider(provider, i);
    throw new IllegalArgumentException();
  }
  
  
  /**
   * De-registers a provider from all service categories it
   * implements.
   *
   * <p>If <code>provider</code> implements the {@link
   * RegisterableService} interface, its {@link
   * RegisterableService#onDeregistration onDeregistration} method is
   * invoked in order to inform the provider about the removal from
   * this registry. If <code>provider</code> implements several
   * service categories, <code>onDeregistration</code> gets called
   * multiple times.</p>
   *
   * @param provider the service provider to be de-registered.
   *
   * @throws IllegalArgumentException if <code>provider</code> is
   * <code>null</code>, or if <code>provider</code> does not implement
   * any of the service categories passed to the {@linkplain
   * #ServiceRegistry(Iterator) constructor} of this
   * <code>ServiceRegistry</code>.
   */
  public synchronized void deregisterServiceProvider(Object provider)
  {
    boolean ok = false;

    if (provider == null)
      throw new IllegalArgumentException();

    for (int i = 0; i < categories.length; i++)
      if (categories[i].isInstance(provider))
        {
          ok = true;
          deregisterServiceProvider(provider, i);
        }

    if (!ok)
      throw new IllegalArgumentException();
  }


  /**
   * De-registers all providers which have been registered for the
   * specified service category.
   *
   * <p>If a provider implements the {@link RegisterableService}
   * interface, its {@link RegisterableService#onDeregistration
   * onDeregistration} method is invoked in order to inform the
   * provider about the removal from this registry. If the provider
   * implements several service categories,
   * <code>onDeregistration</code> gets called multiple times.
   *
   * @param category the category whose registered providers will be
   * de-registered.
   *
   * @throws IllegalArgumentException if <code>category</code> is not
   * among the categories passed to the {@linkplain
   * #ServiceRegistry(Iterator) constructor} of this
   * <code>ServiceRegistry</code>.
   */
  public synchronized void deregisterAll(Class category)
  {
    boolean ok = false;

    for (int i = 0; i < categories.length; i++)
      {
        if (categories[i] != category)
          continue;

        ok = true;
        while (providers[i] != null)
          deregisterServiceProvider(providers[i].get(0), i);
      }

    if (!ok)
      throw new IllegalArgumentException();
  }


  /**
   * De-registers all service providers.
   *
   * <p>If a provider implements the {@link RegisterableService}
   * interface, its {@link RegisterableService#onDeregistration
   * onDeregistration} method is invoked in order to inform the
   * provider about the removal from this registry. If the provider
   * implements several service categories,
   * <code>onDeregistration</code> gets called multiple times.
   */
  public synchronized void deregisterAll()
  {
    for (int i = 0; i < categories.length; i++)
      while (providers[i] != null)
        deregisterServiceProvider(providers[i].get(0), i);
  }


  /**
   * Called by the Virtual Machine when it detects that this
   * <code>ServiceRegistry</code> has become garbage. De-registers all
   * service providers, which will cause those that implement {@link
   * RegisterableService} to receive a {@link
   * RegisterableService#onDeregistration onDeregistration}
   * notification.
   */
  public void finalize()
    throws Throwable
  {
    super.finalize();
    deregisterAll();
  }


  /**
   * Determines whether a provider has been registered with this
   * registry.
   *
   * @return <code>true</code> if <code>provider</code> has been
   * registered under any service category; <code>false</code> if
   * it is not registered.
   *
   * @throws IllegalArgumentException if <code>provider</code> is
   * <code>null</code>.
   */
  public synchronized boolean contains(Object provider)
  {
    if (provider == null)
      throw new IllegalArgumentException();

    // Note that contains is rather unlikely to be ever called,
    // so it would be wasteful to keep a special data structure
    // (such as a HashSet) for making it a fast operation.
    for (int i = 0; i < providers.length; i++)
      {
        // If provider does not implement categories[i],
        // it would not have been possible to register it there.
        // In that case, it would be pointless to look there.
        if (!categories[i].isInstance(provider))
          continue;

        // But if the list of registered providers contains provider,
        // we have found it.
        LinkedList p = providers[i];
        if (p != null && p.contains(provider))
          return true;
      }

    return false;
  }


  /**
   * Returns the index in {@link #categories} occupied by the
   * specified service category.
   *
   * @throws IllegalArgumentException if <code>category</code> is not
   * among the categories passed to the {@linkplain
   * #ServiceRegistry(Iterator) constructor} of this ServiceRegistry.
   */
  private int getCategoryID(Class category)
  {
    for (int i = 0; i < categories.length; i++)
      if (categories[i] == category)
        return i;

    throw new IllegalArgumentException();
  }


  /**
   * Retrieves all providers that have been registered for the
   * specified service category.
   *
   * @param category the service category whose providers are
   * to be retrieved.
   *
   * @param useOrdering <code>true</code> in order to retrieve the
   * providers in an order imposed by the {@linkplain #setOrdering
   * ordering constraints}; <code>false</code> in order to retrieve
   * the providers in any order.
   *
   * @throws IllegalArgumentException if <code>category</code> is not
   * among the categories passed to the {@linkplain
   * #ServiceRegistry(Iterator) constructor} of this
   * <code>ServiceRegistry</code>.
   *
   * @see #getServiceProviders(Class, Filter, boolean)
   */
  public Iterator getServiceProviders(Class category, boolean useOrdering)
  {
    return getServiceProviders(category, null, useOrdering);
  }


  /**
   * Retrieves all providers that have been registered for the
   * specified service category and that satisfy the criteria
   * of a custom filter.
   *
   * @param category the service category whose providers are
   * to be retrieved.
   *
   * @param filter a custom filter, or <code>null</code> to
   * retrieve all registered providers for the specified
   * category.
   *
   * @param useOrdering <code>true</code> in order to retrieve the
   * providers in an order imposed by the {@linkplain #setOrdering
   * ordering constraints}; <code>false</code> in order to retrieve
   * the providers in any order.
   *
   * @throws IllegalArgumentException if <code>category</code> is not
   * among the categories passed to the {@linkplain
   * #ServiceRegistry(Iterator) constructor} of this
   * <code>ServiceRegistry</code>.
   */
  public synchronized Iterator getServiceProviders(Class category,
                                                   Filter filter,
                                                   boolean useOrdering)
  {
    int catid;
    LinkedList provs;
    ArrayList result;

    catid = getCategoryID(category);
    provs = providers[catid];
    if (provs == null)
      return Collections.EMPTY_LIST.iterator();
    
    result = new ArrayList(provs.size());
    for (Iterator iter = provs.iterator(); iter.hasNext();)
      {
        Object provider = iter.next();
        if (filter == null || filter.filter(provider))
          result.add(provider);
      }

    // If we are supposed to obey ordering constraints, and
    // if any constraints have been imposed on the specified
    // service category, sort the result.
    if (useOrdering && constraints != null)
      {
        final Map cons = constraints[catid];
        if (cons != null)
          Collections.sort(result, new Comparator()
            {
              public int compare(Object o1, Object o2)
              {
                Set s;

                if (o1 == o2)
                  return 0;
                
                s = (Set) cons.get(o1);
                if (s != null && s.contains(o2))
                  return -1;  // o1 < o2

                s = (Set) cons.get(o2);
                if (s != null && s.contains(o1))
                  return 1;  // o1 > o2

                return 0; // o1 == o2
              }
            });
      }

    return result.iterator();
  }


  /**
   * Returns one of the service providers that is a subclass of the
   * specified class.
   * 
   * @param providerClass a class to search for.
   */
  public synchronized Object getServiceProviderByClass(Class providerClass)
  {
    if (providerClass == null)
      throw new IllegalArgumentException();

    // Note that the method getServiceProviderByClass is rather
    // unlikely to be ever called, so it would be wasteful to keep a
    // special data structure for making it a fast operation.
    for (int cat = 0; cat < categories.length; cat++)
      {
        if (!categories[cat].isAssignableFrom(providerClass))
          continue;
        
        LinkedList provs = providers[cat];
        if (provs == null)
          continue;

        for (Iterator iter = provs.iterator(); iter.hasNext();)
          {
            Object provider = iter.next();
            if (providerClass.isInstance(provider))
              return provider;
          }
      }

    return null;
  }


  /**
   * Adds an ordering constraint on service providers.
   *
   * @param category the service category to which an ordering
   * constraint is to be added.
   *
   * @param first the provider which is supposed to come before
   * <code>second</code>.
   *
   * @param second the provider which is supposed to come after
   * <code>first</code>.
   *
   * @throws IllegalArgumentException if <code>first</code> and
   * <code>second</code> are referring to the same object, or if one
   * of them is <code>null</code>.
   *
   * @see #unsetOrdering
   * @see #getServiceProviders(Class, Filter, boolean)
   */
  public synchronized boolean setOrdering(Class category,
                                          Object firstProvider,
                                          Object secondProvider)
  {
    return addConstraint(getCategoryID(category), firstProvider,
                         secondProvider);
  }


  /**
   * Removes an ordering constraint on service providers.
   *
   * @param category the service category from which an ordering
   * constraint is to be removed.
   *
   * @param first the provider which is supposed to come before
   * <code>second</code>.
   *
   * @param second the provider which is supposed to come after
   * <code>first</code>.
   *
   * @throws IllegalArgumentException if <code>first</code> and
   * <code>second</code> are referring to the same object, or if one
   * of them is <code>null</code>.
   *
   * @see #setOrdering
   */
  public synchronized boolean unsetOrdering(Class category,
                                            Object firstProvider,
                                            Object secondProvider)
  {
    return removeConstraint(getCategoryID(category),
                            firstProvider, secondProvider);
  }


  /**
   * Adds an ordering constraint on service providers.
   *
   * @param catid the service category ID, which is the
   * category&#x2019;s index into the {@link #categories} array.
   *
   * @param first the provider which is supposed to come before
   * <code>second</code>.
   *
   * @param second the provider which is supposed to come after
   * <code>first</code>.
   *
   * @throws IllegalArgumentException if <code>first</code> and
   * <code>second</code> are referring to the same object, or if one
   * of them is <code>null</code>.
   */
  private boolean addConstraint(int catid, Object first, Object second)
  {
    Set s;
    IdentityHashMap cons;

    // Also checks argument validity.
    removeConstraint(catid, second, first);

    if (constraints == null)
      constraints = new IdentityHashMap[categories.length];
    cons = constraints[catid];
    if (cons == null)
      cons = constraints[catid] = new IdentityHashMap();

    s = (Set) cons.get(first);
    if (s == null)
      cons.put(first, s = new HashSet());
    return s.add(second);
  }


  /**
   * Removes an ordering constraint on service providers.
   *
   * @param catid the service category ID, which is the
   * category&#x2019;s index into the {@link #categories} array.
   *
   * @param first the provider which is supposed to come before
   * <code>second</code>.
   *
   * @param second the provider which is supposed to come after
   * <code>first</code>.
   *
   * @throws IllegalArgumentException if <code>first</code> and
   * <code>second</code> are referring to the same object, or if one
   * of them is <code>null</code>.
   */
  private boolean removeConstraint(int catid, Object first, Object second)
  {
    Collection s;
    IdentityHashMap cons;

    if (first == null || second == null || first == second)
      throw new IllegalArgumentException();

    if (constraints == null)
      return false;

    cons = constraints[catid];
    if (cons == null)
      return false;

    s = (Collection) cons.get(first);
    if (s == null)
      return false;

    if (!s.remove(second))
      return false;

    // If we removed the last constraint for a service category,
    // we can get free some memory.
    if (cons.isEmpty())
      {
        constraints[catid] = null;
        boolean anyConstraints = false;
        for (int i = 0; i < constraints.length; i++)
          {
            if (constraints[i] != null)
              {
                anyConstraints = true;
                break;
              }
          }
        if (!anyConstraints)
          constraints = null;
      }

    return true;
  }


  /**
   * A filter for selecting service providers that match custom
   * criteria.
   *
   * @see ServiceRegistry#getServiceProviders(Class, Filter,
   * boolean)
   *
   * @since 1.4
   *
   * @author Michael Koch (konqueror@gmx.de)
   * @author Sascha Brawer (brawer@dandelis.ch)
   */
  public static interface Filter
  {
    /**
     * Checks whether the specified service provider matches the
     * constraints of this Filter.
     *
     * @param provider the service provider in question.
     *
     * @return <code>true</code> if <code>provider</code> matches the
     * criteria; <code>false</code> if it does not match.
     */
    boolean filter(Object provider);
  };
}

