1. /*
  2. * @(#)IIORegistry.java 1.65 04/06/17
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.imageio.spi;
  8. import java.util.HashMap;
  9. import java.util.Iterator;
  10. import java.util.Map;
  11. import java.util.NoSuchElementException;
  12. import java.util.Set;
  13. import java.util.Vector;
  14. import com.sun.imageio.spi.FileImageInputStreamSpi;
  15. import com.sun.imageio.spi.FileImageOutputStreamSpi;
  16. import com.sun.imageio.spi.InputStreamImageInputStreamSpi;
  17. import com.sun.imageio.spi.OutputStreamImageOutputStreamSpi;
  18. import com.sun.imageio.spi.RAFImageInputStreamSpi;
  19. import com.sun.imageio.spi.RAFImageOutputStreamSpi;
  20. import com.sun.imageio.plugins.gif.GIFImageReaderSpi;
  21. import com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi;
  22. import com.sun.imageio.plugins.jpeg.JPEGImageWriterSpi;
  23. import com.sun.imageio.plugins.png.PNGImageReaderSpi;
  24. import com.sun.imageio.plugins.png.PNGImageWriterSpi;
  25. import com.sun.imageio.plugins.bmp.BMPImageReaderSpi;
  26. import com.sun.imageio.plugins.bmp.BMPImageWriterSpi;
  27. import com.sun.imageio.plugins.wbmp.WBMPImageReaderSpi;
  28. import com.sun.imageio.plugins.wbmp.WBMPImageWriterSpi;
  29. import sun.awt.AppContext;
  30. import sun.misc.Service;
  31. /**
  32. * A registry for service provider instances. Service provider
  33. * classes may be detected at run time by means of meta-information in
  34. * the JAR files containing them. The intent is that it be relatively
  35. * inexpensive to load and inspect all available service provider
  36. * classes. These classes may them be used to locate and instantiate
  37. * more heavyweight classes that will perform actual work, in this
  38. * case instances of <code>ImageReader</code>,
  39. * <code>ImageWriter</code>, <code>ImageTranscoder</code>,
  40. * <code>ImageInputStream</code>, and <code>ImageOutputStream</code>.
  41. *
  42. * <p> Service providers found on the system classpath (<i>e.g.</i>,
  43. * the <code>jre/lib/ext</code> directory in Sun's implementation of
  44. * JDK) are automatically loaded as soon as this class is
  45. * instantiated.
  46. *
  47. * <p> When the <code>registerApplicationClasspathSpis</code> method
  48. * is called, service provider instances declared in the
  49. * meta-information section of JAR files on the application class path
  50. * are loaded. To declare a service provider, a <code>services</code>
  51. * subdirectory is placed within the <code>META-INF</code> directory
  52. * that is present in every JAR file. This directory contains a file
  53. * for each service provider interface that has one or more
  54. * implementation classes present in the JAR file. For example, if
  55. * the JAR file contained a class named
  56. * <code>com.mycompany.imageio.MyFormatReaderSpi</code> which
  57. * implements the <code>ImageReaderSpi</code> interface, the JAR file
  58. * would contain a file named:
  59. *
  60. * <pre>
  61. * META-INF/services/javax.imageio.spi.ImageReaderSpi
  62. * </pre>
  63. *
  64. * containing the line:
  65. *
  66. * <pre>
  67. * com.mycompany.imageio.MyFormatReaderSpi
  68. * </pre>
  69. *
  70. * <p> The service provider classes are intended to be lightweight
  71. * and quick to load. Implementations of these interfaces
  72. * should avoid complex dependencies on other classes and on
  73. * native code.
  74. *
  75. * <p> It is also possible to manually add service providers not found
  76. * automatically, as well as to remove those that are using the
  77. * interfaces of the <code>ServiceRegistry</code> class. Thus
  78. * the application may customize the contents of the registry as it
  79. * sees fit.
  80. *
  81. * <p> For more details on declaring service providers, and the JAR
  82. * format in general, see the <a
  83. * href="{@docRoot}/../guide/jar/jar.html">
  84. * JAR File Specification</a>.
  85. *
  86. * @version 0.5
  87. */
  88. public final class IIORegistry extends ServiceRegistry {
  89. /**
  90. * A <code>Vector</code> containing the valid IIO registry
  91. * categories (superinterfaces) to be used in the constructor.
  92. */
  93. private static final Vector initialCategories = new Vector(5);
  94. static {
  95. initialCategories.add(ImageReaderSpi.class);
  96. initialCategories.add(ImageWriterSpi.class);
  97. initialCategories.add(ImageTranscoderSpi.class);
  98. initialCategories.add(ImageInputStreamSpi.class);
  99. initialCategories.add(ImageOutputStreamSpi.class);
  100. }
  101. /**
  102. * Set up the valid service provider categories and automatically
  103. * register all available service providers.
  104. *
  105. * <p> The constructor is private in order to prevent creation of
  106. * additional instances.
  107. */
  108. private IIORegistry() {
  109. super(initialCategories.iterator());
  110. registerStandardSpis();
  111. registerApplicationClasspathSpis();
  112. }
  113. /**
  114. * Returns the default <code>IIORegistry</code> instance used by
  115. * the Image I/O API. This instance should be used for all
  116. * registry functions.
  117. *
  118. * <p> Each <code>ThreadGroup</code> will receive its own
  119. * instance; this allows different <code>Applet</code>s in the
  120. * same browser (for example) to each have their own registry.
  121. *
  122. * @return the default registry for the current
  123. * <code>ThreadGroup</code>.
  124. */
  125. public static IIORegistry getDefaultInstance() {
  126. AppContext context = AppContext.getAppContext();
  127. IIORegistry registry =
  128. (IIORegistry)context.get(IIORegistry.class);
  129. if (registry == null) {
  130. // Create an instance for this AppContext
  131. registry = new IIORegistry();
  132. context.put(IIORegistry.class, registry);
  133. }
  134. return registry;
  135. }
  136. private void registerStandardSpis() {
  137. // Hardwire standard SPIs
  138. registerServiceProvider(new GIFImageReaderSpi());
  139. registerServiceProvider(new BMPImageReaderSpi());
  140. registerServiceProvider(new BMPImageWriterSpi());
  141. registerServiceProvider(new WBMPImageReaderSpi());
  142. registerServiceProvider(new WBMPImageWriterSpi());
  143. registerServiceProvider(new PNGImageReaderSpi());
  144. registerServiceProvider(new PNGImageWriterSpi());
  145. registerServiceProvider(new JPEGImageReaderSpi());
  146. registerServiceProvider(new JPEGImageWriterSpi());
  147. registerServiceProvider(new FileImageInputStreamSpi());
  148. registerServiceProvider(new FileImageOutputStreamSpi());
  149. registerServiceProvider(new InputStreamImageInputStreamSpi());
  150. registerServiceProvider(new OutputStreamImageOutputStreamSpi());
  151. registerServiceProvider(new RAFImageInputStreamSpi());
  152. registerServiceProvider(new RAFImageOutputStreamSpi());
  153. }
  154. /**
  155. * Registers all available service providers found on the
  156. * application class path, using the default
  157. * <code>ClassLoader</code>. This method is typically invoked by
  158. * the <code>ImageIO.scanForPlugins</code> method.
  159. *
  160. * @see javax.imageio.ImageIO#scanForPlugins
  161. * @see ClassLoader#getResources
  162. */
  163. public void registerApplicationClasspathSpis() {
  164. // FIX: load only from application classpath
  165. ClassLoader loader = Thread.currentThread().getContextClassLoader();
  166. Iterator categories = getCategories();
  167. while (categories.hasNext()) {
  168. Class c = (Class)categories.next();
  169. Iterator riter = Service.providers(c, loader);
  170. while (riter.hasNext()) {
  171. IIOServiceProvider r = (IIOServiceProvider)riter.next();
  172. registerServiceProvider(r);
  173. }
  174. }
  175. }
  176. }