/* * @(#)IIORegistry.java 1.65 04/06/17 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ 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.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 sun.misc.Service; import sun.misc.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 ImageReader, * ImageWriter, ImageTranscoder, * ImageInputStream, and ImageOutputStream. * *

Service providers found on the system classpath (e.g., * the jre/lib/ext directory in Sun's implementation of * JDK) are automatically loaded as soon as this class is * instantiated. * *

When the registerApplicationClasspathSpis 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 services * subdirectory is placed within the META-INF 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 * com.mycompany.imageio.MyFormatReaderSpi which * implements the ImageReaderSpi interface, the JAR file * would contain a file named: * *

 * META-INF/services/javax.imageio.spi.ImageReaderSpi
 * 
* * containing the line: * *
 * com.mycompany.imageio.MyFormatReaderSpi
 * 
* *

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. * *

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 ServiceRegistry class. Thus * the application may customize the contents of the registry as it * sees fit. * *

For more details on declaring service providers, and the JAR * format in general, see the * JAR File Specification. * * @version 0.5 */ public final class IIORegistry extends ServiceRegistry { /** * A Vector 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. * *

The constructor is private in order to prevent creation of * additional instances. */ private IIORegistry() { super(initialCategories.iterator()); registerStandardSpis(); registerApplicationClasspathSpis(); } /** * Returns the default IIORegistry instance used by * the Image I/O API. This instance should be used for all * registry functions. * *

Each ThreadGroup will receive its own * instance; this allows different Applets in the * same browser (for example) to each have their own registry. * * @return the default registry for the current * ThreadGroup. */ 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 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 * ClassLoader. This method is typically invoked by * the ImageIO.scanForPlugins 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 c = (Class)categories.next(); Iterator riter = Service.providers(c, loader); while (riter.hasNext()) { try { 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 c = (Class)categories.next(); Iterator providers = Service.installedProviders(c); while (providers.hasNext()) { IIOServiceProvider p = providers.next(); registerServiceProvider(p); } } return this; } }; AccessController.doPrivileged(doRegistration); } }