/*
 * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.imageio.spi;

import java.security.PrivilegedAction;
import java.security.AccessController;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Vector;
import com.sun.imageio.spi.FileImageInputStreamSpi;
import com.sun.imageio.spi.FileImageOutputStreamSpi;
import com.sun.imageio.spi.InputStreamImageInputStreamSpi;
import com.sun.imageio.spi.OutputStreamImageOutputStreamSpi;
import com.sun.imageio.spi.RAFImageInputStreamSpi;
import com.sun.imageio.spi.RAFImageOutputStreamSpi;
import com.sun.imageio.plugins.gif.GIFImageReaderSpi;
import com.sun.imageio.plugins.gif.GIFImageWriterSpi;
import com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi;
import com.sun.imageio.plugins.jpeg.JPEGImageWriterSpi;
import com.sun.imageio.plugins.png.PNGImageReaderSpi;
import com.sun.imageio.plugins.png.PNGImageWriterSpi;
import com.sun.imageio.plugins.bmp.BMPImageReaderSpi;
import com.sun.imageio.plugins.bmp.BMPImageWriterSpi;
import com.sun.imageio.plugins.wbmp.WBMPImageReaderSpi;
import com.sun.imageio.plugins.wbmp.WBMPImageWriterSpi;
import sun.awt.AppContext;
import java.util.ServiceLoader;
import java.util.ServiceConfigurationError;

/**
 * A registry for service provider instances.  Service provider
 * classes may be detected at run time by means of meta-information in
 * the JAR files containing them.  The intent is that it be relatively
 * inexpensive to load and inspect all available service provider
 * classes.  These classes may them be used to locate and instantiate
 * more heavyweight classes that will perform actual work, in this
 * case instances of <code>ImageReader</code>,
 * <code>ImageWriter</code>, <code>ImageTranscoder</code>,
 * <code>ImageInputStream</code>, and <code>ImageOutputStream</code>.
 *
 * <p> Service providers found on the system classpath (<i>e.g.</i>,
 * the <code>jre/lib/ext</code> directory in Sun's implementation of
 * JDK) are automatically loaded as soon as this class is
 * instantiated.
 *
 * <p> When the <code>registerApplicationClasspathSpis</code> method
 * is called, service provider instances declared in the
 * meta-information section of JAR files on the application class path
 * are loaded.  To declare a service provider, a <code>services</code>
 * subdirectory is placed within the <code>META-INF</code> directory
 * that is present in every JAR file.  This directory contains a file
 * for each service provider interface that has one or more
 * implementation classes present in the JAR file.  For example, if
 * the JAR file contained a class named
 * <code>com.mycompany.imageio.MyFormatReaderSpi</code> which
 * implements the <code>ImageReaderSpi</code> interface, the JAR file
 * would contain a file named:
 *
 * <pre>
 * META-INF/services/javax.imageio.spi.ImageReaderSpi
 * </pre>
 *
 * containing the line:
 *
 * <pre>
 * com.mycompany.imageio.MyFormatReaderSpi
 * </pre>
 *
 * <p> The service provider classes are intended to be lightweight
 * and quick to load.  Implementations of these interfaces
 * should avoid complex dependencies on other classes and on
 * native code.
 *
 * <p> It is also possible to manually add service providers not found
 * automatically, as well as to remove those that are using the
 * interfaces of the <code>ServiceRegistry</code> class.  Thus
 * the application may customize the contents of the registry as it
 * sees fit.
 *
 * <p> For more details on declaring service providers, and the JAR
 * format in general, see the <a
 * href="{@docRoot}/../technotes/guides/jar/jar.html">
 * JAR File Specification</a>.
 *
 */
public final class IIORegistry extends ServiceRegistry {

    /**
     * A <code>Vector</code> containing the valid IIO registry
     * categories (superinterfaces) to be used in the constructor.
     */
    private static final Vector initialCategories = new Vector(5);

    static {
        initialCategories.add(ImageReaderSpi.class);
        initialCategories.add(ImageWriterSpi.class);
        initialCategories.add(ImageTranscoderSpi.class);
        initialCategories.add(ImageInputStreamSpi.class);
        initialCategories.add(ImageOutputStreamSpi.class);
    }

    /**
     * Set up the valid service provider categories and automatically
     * register all available service providers.
     *
     * <p> The constructor is private in order to prevent creation of
     * additional instances.
     */
    private IIORegistry() {
        super(initialCategories.iterator());
        registerStandardSpis();
        registerApplicationClasspathSpis();
    }

    /**
     * Returns the default <code>IIORegistry</code> instance used by
     * the Image I/O API.  This instance should be used for all
     * registry functions.
     *
     * <p> Each <code>ThreadGroup</code> will receive its own
     * instance; this allows different <code>Applet</code>s in the
     * same browser (for example) to each have their own registry.
     *
     * @return the default registry for the current
     * <code>ThreadGroup</code>.
     */
    public static IIORegistry getDefaultInstance() {
        AppContext context = AppContext.getAppContext();
        IIORegistry registry =
            (IIORegistry)context.get(IIORegistry.class);
        if (registry == null) {
            // Create an instance for this AppContext
            registry = new IIORegistry();
            context.put(IIORegistry.class, registry);
        }
        return registry;
    }

    private void registerStandardSpis() {
        // Hardwire standard SPIs
        registerServiceProvider(new GIFImageReaderSpi());
        registerServiceProvider(new GIFImageWriterSpi());
        registerServiceProvider(new BMPImageReaderSpi());
        registerServiceProvider(new BMPImageWriterSpi());
        registerServiceProvider(new WBMPImageReaderSpi());
        registerServiceProvider(new WBMPImageWriterSpi());
        registerServiceProvider(new PNGImageReaderSpi());
        registerServiceProvider(new PNGImageWriterSpi());
        registerServiceProvider(new JPEGImageReaderSpi());
        registerServiceProvider(new JPEGImageWriterSpi());
        registerServiceProvider(new FileImageInputStreamSpi());
        registerServiceProvider(new FileImageOutputStreamSpi());
        registerServiceProvider(new InputStreamImageInputStreamSpi());
        registerServiceProvider(new OutputStreamImageOutputStreamSpi());
        registerServiceProvider(new RAFImageInputStreamSpi());
        registerServiceProvider(new RAFImageOutputStreamSpi());

        registerInstalledProviders();
    }

    /**
     * Registers all available service providers found on the
     * application class path, using the default
     * <code>ClassLoader</code>.  This method is typically invoked by
     * the <code>ImageIO.scanForPlugins</code> method.
     *
     * @see javax.imageio.ImageIO#scanForPlugins
     * @see ClassLoader#getResources
     */
    public void registerApplicationClasspathSpis() {
        // FIX: load only from application classpath

        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        Iterator categories = getCategories();
        while (categories.hasNext()) {
            Class<IIOServiceProvider> c = (Class)categories.next();
            Iterator<IIOServiceProvider> riter =
                    ServiceLoader.load(c, loader).iterator();
            while (riter.hasNext()) {
                try {
                    // Note that the next() call is required to be inside
                    // the try/catch block; see 6342404.
                    IIOServiceProvider r = riter.next();
                    registerServiceProvider(r);
                } catch (ServiceConfigurationError err) {
                    if (System.getSecurityManager() != null) {
                        // In the applet case, we will catch the  error so
                        // registration of other plugins can  proceed
                        err.printStackTrace();
                    } else {
                        // In the application case, we will  throw the
                        // error to indicate app/system  misconfiguration
                        throw err;
                    }
                }
            }
        }
    }

    private void registerInstalledProviders() {
        /*
          We need load installed providers from lib/ext
          directory in the privileged mode in order to
          be able read corresponding jar files even if
          file read capability is restricted (like the
          applet context case).
         */
        PrivilegedAction doRegistration =
            new PrivilegedAction() {
                public Object run() {
                    Iterator categories = getCategories();
                    while (categories.hasNext()) {
                        Class<IIOServiceProvider> c = (Class)categories.next();
                        for (IIOServiceProvider p : ServiceLoader.loadInstalled(c)) {
                            registerServiceProvider(p);
                        }
                    }
                    return this;
                }
            };

        AccessController.doPrivileged(doRegistration);
    }
}
