diff options
Diffstat (limited to 'awt/javax/imageio/spi/ServiceRegistry.java')
-rw-r--r-- | awt/javax/imageio/spi/ServiceRegistry.java | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/awt/javax/imageio/spi/ServiceRegistry.java b/awt/javax/imageio/spi/ServiceRegistry.java new file mode 100644 index 0000000..1a18b02 --- /dev/null +++ b/awt/javax/imageio/spi/ServiceRegistry.java @@ -0,0 +1,516 @@ +/* + * 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. + */ +/** + * @author Rustem V. Rafikov + * @version $Revision: 1.3 $ + */ +package javax.imageio.spi; + +import java.util.*; +import java.util.Map.Entry; + +/** + * The ServiceRegistry class provides ability to register, + * deregister, look up and obtain service provider instances (SPIs). + * A service means a set of interfaces and classes, and a service + * provider is an implementation of a service. Service providers can + * be associated with one or more categories. Each category is defined + * by a class or interface. Only a single instance of a each class is + * allowed to be registered as a category. + */ +public class ServiceRegistry { + + /** The categories. */ + CategoriesMap categories = new CategoriesMap(this); + + /** + * Instantiates a new ServiceRegistry with the specified categories. + * + * @param categoriesIterator an Iterator of Class objects + * for defining of categories. + */ + public ServiceRegistry(Iterator<Class<?>> categoriesIterator) { + if (null == categoriesIterator) { + throw new IllegalArgumentException("categories iterator should not be NULL"); + } + while(categoriesIterator.hasNext()) { + Class<?> c = categoriesIterator.next(); + categories.addCategory(c); + } + } + + /** + * Looks up and instantiates the available providers of this service using + * the specified class loader. + * + * @param providerClass the Class object of the provider to be looked up. + * @param loader the class loader to be used. + * + * @return the iterator of providers objects for this service. + */ + public static <T> Iterator<T> lookupProviders(Class<T> providerClass, ClassLoader loader) { + throw new UnsupportedOperationException("Not supported yet"); + } + + /** + * Looks up and instantiates the available providers of this service using + * the context class loader. + * + * @param providerClass the Class object of the provider to be looked up. + * + * @return the iterator of providers objects for this service. + */ + public static <T> Iterator<T> lookupProviders(Class<T> providerClass) { + return lookupProviders(providerClass, Thread.currentThread().getContextClassLoader()); + } + + /** + * Registers the specified service provider object in the + * specified categories. + * + * @param provider the specified provider to be registered. + * @param category the category. + * + * @return true if no provider of the same class is registered + * in this category, false otherwise. + */ + public <T> boolean registerServiceProvider(T provider, Class<T> category) { + return categories.addProvider(provider, category); + } + + /** + * Registers a list of service providers. + * + * @param providers the list of service providers. + */ + public void registerServiceProviders(Iterator<?> providers) { + for (Iterator<?> iterator = providers; iterator.hasNext();) { + categories.addProvider(iterator.next(), null); + } + } + + /** + * Registers the specified service provider object in all + * categories. + * + * @param provider the service provider. + */ + public void registerServiceProvider(Object provider) { + categories.addProvider(provider, null); + } + + /** + * Deregisters the specifies service provider from the + * specified category. + * + * @param provider the service provider to be deregistered. + * @param category the specified category. + * + * @return true if the provider was already registered + * in the specified category, false otherwise. + */ + public <T> boolean deregisterServiceProvider(T provider, Class<T> category) { + throw new UnsupportedOperationException("Not supported yet"); + } + + /** + * Deregisters the specified service provider from all + * categories. + * + * @param provider the specified service provider. + */ + public void deregisterServiceProvider(Object provider) { + throw new UnsupportedOperationException("Not supported yet"); + } + + /** + * Gets an Iterator of registered service providers + * in the specified category which satisfy the specified Filter. + * The useOrdering parameter indicates whether the iterator will + * return all of the server provider objects in a set order. + * + * @param category the specified category. + * @param filter the specified filter. + * @param useOrdering the flag indicating that providers are ordered + * in the returned Iterator. + * + * @return the iterator of registered service providers. + */ + @SuppressWarnings("unchecked") + public <T> Iterator<T> getServiceProviders(Class<T> category, Filter filter, boolean useOrdering) { + return new FilteredIterator<T>(filter, (Iterator<T>)categories.getProviders(category, useOrdering)); + } + + /** + * Gets an Iterator of all registered service providers + * in the specified category. The useOrdering parameter + * indicates whether the iterator will return all of the server + * provider objects in a set order. + * + * @param category the specified category. + * @param useOrdering the flag indicating that providers are ordered + * in the returned Iterator. + * + * @return the Iterator of service providers. + */ + @SuppressWarnings("unchecked") + public <T> Iterator<T> getServiceProviders(Class<T> category, boolean useOrdering) { + return (Iterator<T>)categories.getProviders(category, useOrdering); + } + + /** + * Gets the registered service provider object that has the + * specified class type. + * + * @param providerClass the specified provider class. + * + * @return the service provider object. + */ + public <T> T getServiceProviderByClass(Class<T> providerClass) { + throw new UnsupportedOperationException("Not supported yet"); + } + + /** + * Sets an ordering between two service provider objects + * within the specified category. + * + * @param category the specified category. + * @param firstProvider the first provider. + * @param secondProvider the second provider. + * + * @return true if a previously unset order was set. + */ + public <T> boolean setOrdering(Class<T> category, T firstProvider, T secondProvider) { + throw new UnsupportedOperationException("Not supported yet"); + } + + /** + * Unsets an ordering between two service provider objects + * within the specified category. + * + * @param category the specified category. + * @param firstProvider the first provider. + * @param secondProvider the second provider. + * + * @return true if a previously unset order was removed. + */ + public <T> boolean unsetOrdering(Class<T> category, T firstProvider, T secondProvider) { + throw new UnsupportedOperationException("Not supported yet"); + } + + /** + * Deregisters all providers from the specified category. + * + * @param category the specified category. + */ + public void deregisterAll(Class<?> category) { + throw new UnsupportedOperationException("Not supported yet"); + } + + /** + * Deregister all providers from all categories. + */ + public void deregisterAll() { + throw new UnsupportedOperationException("Not supported yet"); + } + + /** + * Finalizes this object. + * + * @throws Throwable throws if an error occurs during + * finalization. + */ + @Override + public void finalize() throws Throwable { + //TODO uncomment when deregisterAll is implemented + //deregisterAll(); + } + + /** + * Checks whether the specified provider has been already registered. + * + * @param provider the provider to be checked. + * + * @return true, if the specified provider has been already registered, + * false otherwise. + */ + public boolean contains(Object provider) { + throw new UnsupportedOperationException("Not supported yet"); + } + + /** + * Gets an iterator of Class objects representing the current + * categories. + * + * @return the Iterator of Class objects. + */ + public Iterator<Class<?>> getCategories() { + return categories.list(); + } + + /** + * The ServiceRegistry.Filter interface is used by + * ServiceRegistry.getServiceProviders to filter providers according + * to the specified criterion. + */ + public static interface Filter { + + /** + * Returns true if the specified provider satisfies the + * criterion of this Filter. + * + * @param provider the provider. + * + * @return true if the specified provider satisfies the + * criterion of this Filter, false otherwise. + */ + boolean filter(Object provider); + } + + /** + * The Class CategoriesMap. + */ + private static class CategoriesMap { + + /** The categories. */ + Map<Class<?>, ProvidersMap> categories = new HashMap<Class<?>, ProvidersMap>(); + + /** The registry. */ + ServiceRegistry registry; + + /** + * Instantiates a new categories map. + * + * @param registry the registry + */ + public CategoriesMap(ServiceRegistry registry) { + this.registry = registry; + } + + //-- TODO: useOrdering + /** + * Gets the providers. + * + * @param category the category + * @param useOrdering the use ordering + * + * @return the providers + */ + Iterator<?> getProviders(Class<?> category, boolean useOrdering) { + ProvidersMap providers = categories.get(category); + if (null == providers) { + throw new IllegalArgumentException("Unknown category: " + category); + } + return providers.getProviders(useOrdering); + } + + /** + * List. + * + * @return the iterator< class<?>> + */ + Iterator<Class<?>> list() { + return categories.keySet().iterator(); + } + + /** + * Adds the category. + * + * @param category the category + */ + void addCategory(Class<?> category) { + categories.put(category, new ProvidersMap()); + } + + /** + * Adds a provider to the category. If <code>category</code> is + * <code>null</code> then the provider will be added to all categories + * which the provider is assignable from. + * + * @param provider provider to add + * @param category category to add provider to + * + * @return if there were such provider in some category + */ + boolean addProvider(Object provider, Class<?> category) { + if (provider == null) { + throw new IllegalArgumentException("provider should be != NULL"); + } + + boolean rt; + if (category == null) { + rt = findAndAdd(provider); + } else { + rt = addToNamed(provider, category); + } + + if (provider instanceof RegisterableService) { + ((RegisterableService) provider).onRegistration(registry, category); + } + + return rt; + } + + /** + * Adds the to named. + * + * @param provider the provider + * @param category the category + * + * @return true, if successful + */ + private boolean addToNamed(Object provider, Class<?> category) { + Object obj = categories.get(category); + + if (null == obj) { + throw new IllegalArgumentException("Unknown category: " + category); + } + + return ((ProvidersMap) obj).addProvider(provider); + } + + /** + * Find and add. + * + * @param provider the provider + * + * @return true, if successful + */ + private boolean findAndAdd(Object provider) { + boolean rt = false; + for (Entry<Class<?>, ProvidersMap> e : categories.entrySet()) { + if (e.getKey().isAssignableFrom(provider.getClass())) { + rt |= e.getValue().addProvider(provider); + } + } + return rt; + } + } + + /** + * The Class ProvidersMap. + */ + private static class ProvidersMap { + //-- TODO: providers ordering support + + /** The providers. */ + Map<Class<?>, Object> providers = new HashMap<Class<?>, Object>(); + + /** + * Adds the provider. + * + * @param provider the provider + * + * @return true, if successful + */ + boolean addProvider(Object provider) { + return providers.put(provider.getClass(), provider) != null; + } + + /** + * Gets the provider classes. + * + * @return the provider classes + */ + Iterator<Class<?>> getProviderClasses() { + return providers.keySet().iterator(); + } + + //-- TODO ordering + /** + * Gets the providers. + * + * @param userOrdering the user ordering + * + * @return the providers + */ + Iterator<?> getProviders(boolean userOrdering) { + return providers.values().iterator(); + } + } + + /** + * The Class FilteredIterator. + */ + private static class FilteredIterator<E> implements Iterator<E> { + + /** The filter. */ + private Filter filter; + + /** The backend. */ + private Iterator<E> backend; + + /** The next obj. */ + private E nextObj; + + /** + * Instantiates a new filtered iterator. + * + * @param filter the filter + * @param backend the backend + */ + public FilteredIterator(Filter filter, Iterator<E> backend) { + this.filter = filter; + this.backend = backend; + findNext(); + } + + /** + * Next. + * + * @return the e + */ + public E next() { + if (nextObj == null) { + throw new NoSuchElementException(); + } + E tmp = nextObj; + findNext(); + return tmp; + } + + /** + * Checks for next. + * + * @return true, if successful + */ + public boolean hasNext() { + return nextObj != null; + } + + /** + * Removes the. + */ + public void remove() { + throw new UnsupportedOperationException(); + } + + /** + * Sets nextObj to a next provider matching the criterion given by the filter. + */ + private void findNext() { + nextObj = null; + while (backend.hasNext()) { + E o = backend.next(); + if (filter.filter(o)) { + nextObj = o; + return; + } + } + } + } +} |