Initial Contribution
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;
+                }
+            }
+        }
+    }
+}