Java/Reflection/OSGI

Материал из Java эксперт
Перейти к: навигация, поиск

Maintains a mapping of service names to an ordered set of service providers when running in an OSGi container.

 
/*
 * Licensed 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.
 */
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
/**
 * Maintains a mapping of service names to an ordered set of service providers
 * when running in an OSGi container. <p/> It is expected that a bundle using
 * Drools will populate this map with properties from its own ClassLoader. <p/>
 * This is an adaptation of the technique described by Guillaume Nodet in his
 * article<i> </i>. The main changes were to add comments.
 * 
 * @author Guillaume Nodet
 * @author Faron Dutton
 * @see {@linkplain http://gnodet.blogspot.ru/2008/05/jee-specs-in-osgi.html}
 */
public final class OSGiLocator {
  /**
   * Maps a service name (the fully qualified name of the interface) to an
   * ordered set of factories. Each factory instantiating a specific service
   * provider (implementation).
   */
  private static Map<String, List<Callable<Class<?>>>> factories;
  /**
   * Private constructor used to prevent instantiation of this utility class
   * (i.e., Utility Pattern).
   */
  private OSGiLocator() {
    super();
  }
  /**
   * Removes the given service provider factory from the set of providers for
   * the service.
   * 
   * @param serviceName
   *          The fully qualified name of the service interface.
   * @param factory
   *          A factory for creating a specific type of service provider. May be
   *          <tt>null</tt> in which case this method does nothing.
   * @throws IllegalArgumentException
   *           if serviceName is <tt>null</tt>
   */
  public static synchronized void unregister(final String serviceName,
      final Callable<Class<?>> factory) {
    if (serviceName == null) {
      throw new IllegalArgumentException("serviceName cannot be null");
    }
    if (factories != null) {
      List<Callable<Class<?>>> l = factories.get(serviceName);
      if (l != null) {
        l.remove(factory);
      }
    }
  }
  /**
   * Adds the given service provider factory to the set of providers for the
   * service.
   * 
   * @param serviceName
   *          The fully qualified name of the service interface.
   * @param factory
   *          A factory for creating a specific type of service provider. May be
   *          <tt>null</tt> in which case this method does nothing.
   * @throws IllegalArgumentException
   *           if serviceName is <tt>null</tt>
   */
  public static synchronized void register(final String serviceName,
      final Callable<Class<?>> factory) {
    if (serviceName == null) {
      throw new IllegalArgumentException("serviceName cannot be null");
    }
    if (factory != null) {
      if (factories == null) {
        factories = new HashMap<String, List<Callable<Class<?>>>>();
      }
      List<Callable<Class<?>>> l = factories.get(serviceName);
      if (l == null) {
        l = new ArrayList<Callable<Class<?>>>();
        factories.put(serviceName, l);
      }
      l.add(factory);
    }
  }
  /**
   * Finds the preferred provider for the given service. The preferred provider
   * is the last one added to the set of providers.
   * 
   * @param serviceName
   *          The fully qualified name of the service interface.
   * @return The last provider added for the service if any exists. Otherwise,
   *         it returns <tt>null</tt>.
   * @throws IllegalArgumentException
   *           if serviceName is <tt>null</tt>
   */
  public static synchronized Class<?> locate(final String serviceName) {
    if (serviceName == null) {
      throw new IllegalArgumentException("serviceName cannot be null");
    }
    if (factories != null) {
      List<Callable<Class<?>>> l = factories.get(serviceName);
      if (l != null && !l.isEmpty()) {
        Callable<Class<?>> c = l.get(l.size() - 1);
        try {
          return c.call();
        } catch (Exception e) {
        }
      }
    }
    return null;
  }
  /**
   * Finds all providers for the given service.
   * 
   * @param serviceName
   *          The fully qualified name of the service interface.
   * @return The ordered set of providers for the service if any exists.
   *         Otherwise, it returns an empty list.
   * @throws IllegalArgumentException
   *           if serviceName is <tt>null</tt>
   */
  public static synchronized List<Class<?>> locateAll(final String serviceName) {
    if (serviceName == null) {
      throw new IllegalArgumentException("serviceName cannot be null");
    }
    List<Class<?>> classes = new ArrayList<Class<?>>();
    if (factories != null) {
      List<Callable<Class<?>>> l = factories.get(serviceName);
      if (l != null) {
        for (Callable<Class<?>> c : l) {
          try {
            classes.add(c.call());
          } catch (Exception e) {
          }
        }
      }
    }
    return classes;
  }
}