2004-04-21 Michael Koch <konqueror@gmx.de>
authormkoch <mkoch@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Apr 2004 08:20:31 +0000 (08:20 +0000)
committermkoch <mkoch@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Apr 2004 08:20:31 +0000 (08:20 +0000)
* gnu/classpath/ServiceFactory.java,
gnu/classpath/ServiceProviderLoadingAction.java,
javax/imageio/ImageReader.java,
javax/imageio/ImageTranscoder.java,
javax/imageio/ImageWriter.java,
javax/imageio/package.html,
javax/imageio/spi/IIOServiceProvider.java,
javax/imageio/spi/ImageInputStreamSpi.java,
javax/imageio/spi/ImageOutputStreamSpi.java,
javax/imageio/spi/ImageReaderWriterSpi.java,
javax/imageio/spi/ImageTranscoderSpi.java,
javax/imageio/spi/RegisterableService.java,
javax/imageio/spi/ServiceRegistry.java,
javax/imageio/spi/package.html,
javax/imageio/stream/IIOByteBuffer.java,
javax/imageio/stream/ImageInputStream.java,
javax/imageio/stream/ImageOutputStream.java,
javax/imageio/stream/package.html:
New files.
* Makefile.am
(ordinary_java_source_files): Added
gnu/classpath/ServiceFactory.java and
gnu/classpath/ServiceProviderLoadingAction.java.
(javax_source_files): Added
javax/imageio/ImageReader.java,
javax/imageio/ImageTranscoder.java,
javax/imageio/ImageWriter.java,
javax/imageio/spi/IIOServiceProvider.java,
javax/imageio/spi/ImageInputStreamSpi.java,
javax/imageio/spi/ImageOutputStreamSpi.java,
javax/imageio/spi/ImageReaderWriterSpi.java,
javax/imageio/spi/ImageTranscoderSpi.java,
javax/imageio/spi/RegisterableService.java,
javax/imageio/spi/ServiceRegistry.java,
javax/imageio/stream/IIOByteBuffer.java,
javax/imageio/stream/ImageInputStream.java and
javax/imageio/stream/ImageOutputStream.java.
* Makefile.in: Regenerated.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@80951 138bc75d-0d04-0410-961f-82ee72b054a4

21 files changed:
libjava/ChangeLog
libjava/Makefile.am
libjava/Makefile.in
libjava/gnu/classpath/ServiceFactory.java [new file with mode: 0644]
libjava/gnu/classpath/ServiceProviderLoadingAction.java [new file with mode: 0644]
libjava/javax/imageio/ImageReader.java [new file with mode: 0644]
libjava/javax/imageio/ImageTranscoder.java [new file with mode: 0644]
libjava/javax/imageio/ImageWriter.java [new file with mode: 0644]
libjava/javax/imageio/package.html [new file with mode: 0644]
libjava/javax/imageio/spi/IIOServiceProvider.java [new file with mode: 0644]
libjava/javax/imageio/spi/ImageInputStreamSpi.java [new file with mode: 0644]
libjava/javax/imageio/spi/ImageOutputStreamSpi.java [new file with mode: 0644]
libjava/javax/imageio/spi/ImageReaderWriterSpi.java [new file with mode: 0644]
libjava/javax/imageio/spi/ImageTranscoderSpi.java [new file with mode: 0644]
libjava/javax/imageio/spi/RegisterableService.java [new file with mode: 0644]
libjava/javax/imageio/spi/ServiceRegistry.java [new file with mode: 0644]
libjava/javax/imageio/spi/package.html [new file with mode: 0644]
libjava/javax/imageio/stream/IIOByteBuffer.java [new file with mode: 0644]
libjava/javax/imageio/stream/ImageInputStream.java [new file with mode: 0644]
libjava/javax/imageio/stream/ImageOutputStream.java [new file with mode: 0644]
libjava/javax/imageio/stream/package.html [new file with mode: 0644]

index c426ddb..b8bcec2 100644 (file)
@@ -1,5 +1,46 @@
 2004-04-21  Michael Koch  <konqueror@gmx.de>
 
+       * gnu/classpath/ServiceFactory.java,
+       gnu/classpath/ServiceProviderLoadingAction.java,
+       javax/imageio/ImageReader.java,
+       javax/imageio/ImageTranscoder.java,
+       javax/imageio/ImageWriter.java,
+       javax/imageio/package.html,
+       javax/imageio/spi/IIOServiceProvider.java,
+       javax/imageio/spi/ImageInputStreamSpi.java,
+       javax/imageio/spi/ImageOutputStreamSpi.java,
+       javax/imageio/spi/ImageReaderWriterSpi.java,
+       javax/imageio/spi/ImageTranscoderSpi.java,
+       javax/imageio/spi/RegisterableService.java,
+       javax/imageio/spi/ServiceRegistry.java,
+       javax/imageio/spi/package.html,
+       javax/imageio/stream/IIOByteBuffer.java,
+       javax/imageio/stream/ImageInputStream.java,
+       javax/imageio/stream/ImageOutputStream.java,
+       javax/imageio/stream/package.html:
+       New files.
+       * Makefile.am
+       (ordinary_java_source_files): Added
+       gnu/classpath/ServiceFactory.java and
+       gnu/classpath/ServiceProviderLoadingAction.java.
+       (javax_source_files): Added
+       javax/imageio/ImageReader.java,
+       javax/imageio/ImageTranscoder.java,
+       javax/imageio/ImageWriter.java,
+       javax/imageio/spi/IIOServiceProvider.java,
+       javax/imageio/spi/ImageInputStreamSpi.java,
+       javax/imageio/spi/ImageOutputStreamSpi.java,
+       javax/imageio/spi/ImageReaderWriterSpi.java,
+       javax/imageio/spi/ImageTranscoderSpi.java,
+       javax/imageio/spi/RegisterableService.java,
+       javax/imageio/spi/ServiceRegistry.java,
+       javax/imageio/stream/IIOByteBuffer.java,
+       javax/imageio/stream/ImageInputStream.java and
+       javax/imageio/stream/ImageOutputStream.java.
+       * Makefile.in: Regenerated.
+
+2004-04-21  Michael Koch  <konqueror@gmx.de>
+
        * java/util/Properties.java
        (load): Fix wrongly merged fix.
 
index 31cbb47..ff8f36d 100644 (file)
@@ -1748,6 +1748,19 @@ javax/accessibility/AccessibleTable.java \
 javax/accessibility/AccessibleTableModelChange.java \
 javax/accessibility/AccessibleText.java \
 javax/accessibility/AccessibleValue.java \
+javax/imageio/ImageReader.java \
+javax/imageio/ImageTranscoder.java \
+javax/imageio/ImageWriter.java \
+javax/imageio/spi/IIOServiceProvider.java \
+javax/imageio/spi/ImageInputStreamSpi.java \
+javax/imageio/spi/ImageOutputStreamSpi.java \
+javax/imageio/spi/ImageReaderWriterSpi.java \
+javax/imageio/spi/ImageTranscoderSpi.java \
+javax/imageio/spi/RegisterableService.java \
+javax/imageio/spi/ServiceRegistry.java \
+javax/imageio/stream/IIOByteBuffer.java \
+javax/imageio/stream/ImageInputStream.java \
+javax/imageio/stream/ImageOutputStream.java \
 javax/naming/directory/Attribute.java \
 javax/naming/directory/AttributeInUseException.java \
 javax/naming/directory/AttributeModificationException.java \
@@ -2187,6 +2200,8 @@ java/util/regex/PatternSyntaxException.java
 ## awt_java_source_files.  If the .java file has a hand-maintained
 ## header, please list it in special_java_source_files.
 ordinary_java_source_files = $(core_java_source_files) \
+gnu/classpath/ServiceFactory.java \
+gnu/classpath/ServiceProviderLoadingAction.java \
 gnu/gcj/Core.java \
 gnu/gcj/RawData.java \
 gnu/gcj/io/DefaultMimeTypes.java \
index 71e4b9b..12dd828 100644 (file)
@@ -1432,6 +1432,19 @@ javax/accessibility/AccessibleTable.java \
 javax/accessibility/AccessibleTableModelChange.java \
 javax/accessibility/AccessibleText.java \
 javax/accessibility/AccessibleValue.java \
+javax/imageio/ImageReader.java \
+javax/imageio/ImageTranscoder.java \
+javax/imageio/ImageWriter.java \
+javax/imageio/spi/IIOServiceProvider.java \
+javax/imageio/spi/ImageInputStreamSpi.java \
+javax/imageio/spi/ImageOutputStreamSpi.java \
+javax/imageio/spi/ImageReaderWriterSpi.java \
+javax/imageio/spi/ImageTranscoderSpi.java \
+javax/imageio/spi/RegisterableService.java \
+javax/imageio/spi/ServiceRegistry.java \
+javax/imageio/stream/IIOByteBuffer.java \
+javax/imageio/stream/ImageInputStream.java \
+javax/imageio/stream/ImageOutputStream.java \
 javax/naming/directory/Attribute.java \
 javax/naming/directory/AttributeInUseException.java \
 javax/naming/directory/AttributeModificationException.java \
@@ -1862,6 +1875,8 @@ java/util/regex/PatternSyntaxException.java
 
 
 ordinary_java_source_files = $(core_java_source_files) \
+gnu/classpath/ServiceFactory.java \
+gnu/classpath/ServiceProviderLoadingAction.java \
 gnu/gcj/Core.java \
 gnu/gcj/RawData.java \
 gnu/gcj/io/DefaultMimeTypes.java \
@@ -3010,9 +3025,10 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/gnu/awt/xlib/XGraphicsConfiguration.P \
 .deps/gnu/awt/xlib/XOffScreenImage.P .deps/gnu/awt/xlib/XPanelPeer.P \
 .deps/gnu/awt/xlib/XToolkit.P .deps/gnu/classpath/Configuration.P \
-.deps/gnu/gcj/Core.P .deps/gnu/gcj/RawData.P \
-.deps/gnu/gcj/convert/BytesToUnicode.P .deps/gnu/gcj/convert/Convert.P \
-.deps/gnu/gcj/convert/IOConverter.P \
+.deps/gnu/classpath/ServiceFactory.P \
+.deps/gnu/classpath/ServiceProviderLoadingAction.P .deps/gnu/gcj/Core.P \
+.deps/gnu/gcj/RawData.P .deps/gnu/gcj/convert/BytesToUnicode.P \
+.deps/gnu/gcj/convert/Convert.P .deps/gnu/gcj/convert/IOConverter.P \
 .deps/gnu/gcj/convert/Input_8859_1.P \
 .deps/gnu/gcj/convert/Input_ASCII.P \
 .deps/gnu/gcj/convert/Input_EUCJIS.P \
@@ -4233,6 +4249,18 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/javax/accessibility/AccessibleTableModelChange.P \
 .deps/javax/accessibility/AccessibleText.P \
 .deps/javax/accessibility/AccessibleValue.P \
+.deps/javax/imageio/ImageReader.P .deps/javax/imageio/ImageTranscoder.P \
+.deps/javax/imageio/ImageWriter.P \
+.deps/javax/imageio/spi/IIOServiceProvider.P \
+.deps/javax/imageio/spi/ImageInputStreamSpi.P \
+.deps/javax/imageio/spi/ImageOutputStreamSpi.P \
+.deps/javax/imageio/spi/ImageReaderWriterSpi.P \
+.deps/javax/imageio/spi/ImageTranscoderSpi.P \
+.deps/javax/imageio/spi/RegisterableService.P \
+.deps/javax/imageio/spi/ServiceRegistry.P \
+.deps/javax/imageio/stream/IIOByteBuffer.P \
+.deps/javax/imageio/stream/ImageInputStream.P \
+.deps/javax/imageio/stream/ImageOutputStream.P \
 .deps/javax/naming/AuthenticationException.P \
 .deps/javax/naming/AuthenticationNotSupportedException.P \
 .deps/javax/naming/BinaryRefAddr.P .deps/javax/naming/Binding.P \
diff --git a/libjava/gnu/classpath/ServiceFactory.java b/libjava/gnu/classpath/ServiceFactory.java
new file mode 100644 (file)
index 0000000..0e81cf7
--- /dev/null
@@ -0,0 +1,576 @@
+/* ServiceFactory.java -- Factory for plug-in services.
+   Copyright (C) 2004  Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.classpath;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.LogRecord;
+
+
+/**
+ * A factory for plug-ins that conform to a service provider
+ * interface. This is a general mechanism that gets used by a number
+ * of packages in the Java API. For instance, {@link
+ * java.nio.charset.spi.CharsetProvider} allows to write custom
+ * encoders and decoders for character sets, {@link
+ * javax.imageio.spi.ImageReaderSpi} allows to support custom image
+ * formats, and {@link javax.print.PrintService} makes it possible to
+ * write custom printer drivers.
+ *
+ * <p>The plug-ins are concrete implementations of the service
+ * provider interface, which is defined as an interface or an abstract
+ * class. The implementation classes must be public and have a public
+ * constructor that takes no arguments.
+ *
+ * <p>Plug-ins are usually deployed in JAR files. A JAR that provides
+ * an implementation of a service must declare this in a resource file
+ * whose name is the fully qualified service name and whose location
+ * is the directory <code>META-INF/services</code>. This UTF-8 encoded
+ * text file lists, on separate lines, the fully qualified names of
+ * the concrete implementations. Thus, one JAR file can provide an
+ * arbitrary number of implementations for an arbitrary count of
+ * service provider interfaces.
+ *
+ * <p><b>Example</b>
+ *
+ * <p>For example, a JAR might provide two implementations of the
+ * service provider interface <code>org.foo.ThinkService</code>,
+ * namely <code>com.acme.QuickThinker</code> and
+ * <code>com.acme.DeepThinker</code>. The code for <code>QuickThinker</code>
+ * woud look as follows:
+ *
+ * <pre>
+ * package com.acme;
+ *
+ * &#x2f;**
+ * * Provices a super-quick, but not very deep implementation of ThinkService.
+ * *&#x2f;
+ * public class QuickThinker
+ *   implements org.foo.ThinkService
+ * {
+ *   &#x2f;**
+ *   * Constructs a new QuickThinker. The service factory (which is
+ *   * part of the Java environment) calls this no-argument constructor
+ *   * when it looks up the available implementations of ThinkService.
+ *   *
+ *   * &lt;p&gt;Note that an application might query all available
+ *   * ThinkService providers, but use just one of them. Therefore,
+ *   * constructing an instance should be very inexpensive. For example,
+ *   * large data structures should only be allocated when the service
+ *   * actually gets used.
+ *   *&#x2f;
+ *   public QuickThinker()
+ *   {
+ *   }
+ *
+ *   &#x2f;**
+ *   * Returns the speed of this ThinkService in thoughts per second.
+ *   * Applications can choose among the available service providers
+ *   * based on this value.
+ *   *&#x2f;
+ *   public double getSpeed()
+ *   {
+ *     return 314159.2654;
+ *   }
+ *
+ *   &#x2f;**
+ *   * Produces a thought. While the returned thoughts are not very
+ *   * deep, they are generated in very short time.
+ *   *&#x2f;
+ *   public Thought think()
+ *   {
+ *     return null;
+ *   }
+ * }
+ * </pre>
+ *
+ * <p>The code for <code>com.acme.DeepThinker</code> is left as an
+ * exercise to the reader.
+ *
+ * <p>Acme&#x2019;s <code>ThinkService</code> plug-in gets deployed as
+ * a JAR file. Besides the bytecode and resources for
+ * <code>QuickThinker</code> and <code>DeepThinker</code>, it also
+ * contains the text file
+ * <code>META-INF/services/org.foo.ThinkService</code>:
+ *
+ * <pre>
+ * # Available implementations of org.foo.ThinkService
+ * com.acme.QuickThinker
+ * com.acme.DeepThinker
+ * </pre>
+ *
+ * <p><b>Thread Safety</b>
+ *
+ * <p>It is safe to use <code>ServiceFactory</code> from multiple
+ * concurrent threads without external synchronization.
+ *
+ * <p><b>Note for User Applications</b>
+ *
+ * <p>User applications that want to load plug-ins should not directly
+ * use <code>gnu.classpath.ServiceFactory</code>, because this class
+ * is only available in Java environments that are based on GNU
+ * Classpath. Instead, it is recommended that user applications call
+ * {@link
+ * javax.imageio.spi.ServiceRegistry#lookupProviders(Class)}. This API
+ * is actually independent of image I/O, and it is available on every
+ * environment.
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public final class ServiceFactory
+{
+  /**
+   * A logger that gets informed when a service gets loaded, or
+   * when there is a problem with loading a service.
+   *
+   * <p>Because {@link java.util.logging.Logger#getLogger(String)}
+   * is thread-safe, we do not need to worry about synchronization
+   * here.
+   */
+  private static final Logger LOGGER = Logger.getLogger("gnu.classpath");
+
+
+  /**
+   * Declared private in order to prevent constructing instances of
+   * this utility class.
+   */
+  private ServiceFactory()
+  {
+  }
+
+
+  /**
+   * Finds service providers that are implementing the specified
+   * Service Provider Interface.
+   *
+   * <p><b>On-demand loading:</b> Loading and initializing service
+   * providers is delayed as much as possible. The rationale is that
+   * typical clients will iterate through the set of installed service
+   * providers until one is found that matches some criteria (like
+   * supported formats, or quality of service). In such scenarios, it
+   * might make sense to install only the frequently needed service
+   * providers on the local machine. More exotic providers can be put
+   * onto a server; the server will only be contacted when no suitable
+   * service could be found locally.
+   *
+   * <p><b>Security considerations:</b> Any loaded service providers
+   * are loaded through the specified ClassLoader, or the system
+   * ClassLoader if <code>classLoader</code> is
+   * <code>null</code>. When <code>lookupProviders</code> is called,
+   * the current {@link AccessControlContext} gets recorded. This
+   * captured security context will determine the permissions when
+   * services get loaded via the <code>next()</code> method of the
+   * returned <code>Iterator</code>.
+   *
+   * @param spi the service provider interface which must be
+   * implemented by any loaded service providers.
+   *
+   * @param loader the class loader that will be used to load the
+   * service providers, or <code>null</code> for the system class
+   * loader. For using the context class loader, see {@link
+   * #lookupProviders(Class)}.
+   *
+   * @return an iterator over instances of <code>spi</code>.
+   *
+   * @throws IllegalArgumentException if <code>spi</code> is
+   * <code>null</code>.
+   */
+  public static Iterator lookupProviders(Class spi,
+                                         ClassLoader loader)
+  {
+    InputStream stream;
+    String resourceName;
+    Enumeration urls;
+
+    if (spi == null)
+      throw new IllegalArgumentException();
+
+    if (loader == null)
+      loader = ClassLoader.getSystemClassLoader();
+
+    resourceName = "META-INF/services/" + spi.getName();
+    try
+      {
+        urls = loader.getResources(resourceName);
+      }
+    catch (IOException ioex)
+      {
+        /* If an I/O error occurs here, we cannot provide any service
+         * providers. In this case, we simply return an iterator that
+         * does not return anything (no providers installed).
+         */
+        log(Level.WARNING, "cannot access {0}", resourceName, ioex);
+        return Collections.EMPTY_LIST.iterator();
+      }
+
+    return new ServiceIterator(spi, urls, loader,
+                               AccessController.getContext());
+  }
+
+
+  /**
+   * Finds service providers that are implementing the specified
+   * Service Provider Interface, using the context class loader
+   * for loading providers.
+   *
+   * @param spi the service provider interface which must be
+   * implemented by any loaded service providers.
+   *
+   * @return an iterator over instances of <code>spi</code>.
+   *
+   * @throws IllegalArgumentException if <code>spi</code> is
+   * <code>null</code>.
+   *
+   * @see #lookupProviders(Class, ClassLoader)
+   */
+  public static Iterator lookupProviders(Class spi)
+  {
+    ClassLoader ctxLoader;
+
+    ctxLoader = Thread.currentThread().getContextClassLoader();
+    return lookupProviders(spi, ctxLoader);
+  }
+
+
+  /**
+   * An iterator over service providers that are listed in service
+   * provider configuration files, which get passed as an Enumeration
+   * of URLs. This is a helper class for {@link
+   * ServiceFactory#lookupProviders}.
+   *
+   * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+   */
+  private static final class ServiceIterator
+    implements Iterator
+  {
+    /**
+     * The service provider interface (usually an interface, sometimes
+     * an abstract class) which the services must implement.
+     */
+    private final Class spi;
+
+
+    /**
+     * An Enumeration<URL> over the URLs that contain a resource
+     * <code>META-INF/services/&lt;org.foo.SomeService&gt;</code>,
+     * as returned by {@link ClassLoader#getResources(String)}.
+     */
+    private final Enumeration urls;
+
+
+    /**
+     * The class loader used for loading service providers.
+     */
+    private final ClassLoader loader;
+
+
+    /**
+     * The security context used when loading and initializing service
+     * providers. We want to load and initialize all plug-in service
+     * providers under the same security context, namely the one that
+     * was active when {@link #lookupProviders} has been called.
+     */
+    private final AccessControlContext securityContext;
+
+
+    /**
+     * A reader for the current file listing class names of service
+     * implementors, or <code>null</code> when the last reader has
+     * been fetched.
+     */
+    private BufferedReader reader;
+    
+
+    /**
+     * The URL currently being processed. This is only used for
+     * emitting error messages.
+     */
+    private URL currentURL;
+
+
+    /**
+     * The service provider that will be returned by the next call to
+     * {@link #next()}, or <code>null</code> if the iterator has
+     * already returned all service providers.
+     */
+    private Object nextProvider;
+
+
+    /**
+     * Constructs an Iterator that loads and initializes services on
+     * demand.
+     *
+     * @param spi the service provider interface which the services
+     * must implement. Usually, this is a Java interface type, but it
+     * might also be an abstract class or even a concrete superclass.
+     *
+     * @param urls an Enumeration<URL> over the URLs that contain a
+     * resource
+     * <code>META-INF/services/&lt;org.foo.SomeService&gt;</code>, as
+     * determined by {@link ClassLoader#getResources(String)}.
+     *
+     * @param loader the ClassLoader that gets used for loading
+     * service providers.
+     *
+     * @param securityContext the security context to use when loading
+     * and initializing service providers.
+     */
+    ServiceIterator(Class spi, Enumeration urls, ClassLoader loader,
+                    AccessControlContext securityContext)
+    {
+      this.spi = spi;
+      this.urls = urls;
+      this.loader = loader;
+      this.securityContext = securityContext;
+      this.nextProvider = loadNextServiceProvider();
+    }
+
+
+    /**
+     * @throws NoSuchElementException if {@link #hasNext} returns
+     * <code>false</code>.
+     */
+    public Object next()
+    {
+      Object result;
+
+      if (!hasNext())
+        throw new NoSuchElementException();
+
+      result = nextProvider;
+      nextProvider = loadNextServiceProvider();
+      return result;
+    }
+
+
+    public boolean hasNext()
+    {
+      return nextProvider != null;
+    }
+
+
+    public void remove()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+
+    private Object loadNextServiceProvider()
+    {
+      String line;
+      Class klass;
+      
+      if (reader == null)
+        advanceReader();
+
+      for (;;)
+        {
+          /* If we have reached the last provider list, we cannot
+           * retrieve any further lines.
+           */
+          if (reader == null)
+            return null;
+
+          try
+            {
+              line = reader.readLine();
+            }
+          catch (IOException readProblem)
+            {
+              log(Level.WARNING, "IOException upon reading {0}", currentURL,
+                  readProblem);
+              line = null;
+            }
+
+          /* When we are at the end of one list of services,
+           * switch over to the next one.
+           */
+          if (line == null)
+            {
+              advanceReader();
+              continue;
+            }
+
+
+          // Skip whitespace at the beginning and end of each line.
+          line = line.trim();
+
+          // Skip empty lines.
+          if (line.length() == 0)
+            continue;
+
+          // Skip comment lines.
+          if (line.charAt(0) == '#')
+            continue;
+
+          try
+            {
+              log(Level.FINE,
+                  "Loading service provider \"{0}\", specified"
+                  + " by \"META-INF/services/{1}\" in {2}.",
+                  new Object[] { line, spi.getName(), currentURL },
+                  null);
+
+              /* Load the class in the security context that was
+               * active when calling lookupProviders.
+               */
+              return AccessController.doPrivileged(
+                new ServiceProviderLoadingAction(spi, line, loader),
+                securityContext);
+            }
+          catch (Exception ex)
+            {
+              String msg = "Cannot load service provider class \"{0}\","
+                + " specified by \"META-INF/services/{1}\" in {2}";
+              if (ex instanceof PrivilegedActionException
+                  && ex.getCause() instanceof ClassCastException)
+                msg = "Service provider class \"{0}\" is not an instance"
+                  + " of \"{1}\". Specified"
+                  + " by \"META-INF/services/{1}\" in {2}.";
+
+              log(Level.WARNING, msg,                  
+                  new Object[] { line, spi.getName(), currentURL },
+                  ex);
+              continue;
+            }
+        }
+    }
+
+
+    private void advanceReader()
+    {
+      do
+        {
+          if (reader != null)
+            {
+              try
+                {
+                  reader.close();
+                  log(Level.FINE, "closed {0}", currentURL, null);
+                }
+              catch (Exception ex)
+                {
+                  log(Level.WARNING, "cannot close {0}", currentURL, ex);
+                }
+              reader = null;
+              currentURL = null;
+            }
+
+        if (!urls.hasMoreElements())
+          return;
+
+        currentURL = (URL) urls.nextElement();
+        try
+          {
+            reader = new BufferedReader(new InputStreamReader(
+              currentURL.openStream(), "UTF-8"));
+            log(Level.FINE, "opened {0}", currentURL, null);
+          }
+        catch (Exception ex)
+          {
+            log(Level.WARNING, "cannot open {0}", currentURL, ex);
+          }
+        }
+      while (reader == null);
+    }
+  }
+
+
+  /**
+   * Passes a log message to the <code>java.util.logging</code>
+   * framework. This call returns very quickly if no log message will
+   * be produced, so there is not much overhead in the standard case.
+   *
+   * @param the severity of the message, for instance {@link
+   * Level#WARNING}.
+   *
+   * @param msg the log message, for instance <code>&#x201c;Could not
+   * load {0}.&#x201d;</code>
+   *
+   * @param param the parameter(s) for the log message, or
+   * <code>null</code> if <code>msg</code> does not specify any
+   * parameters. If <code>param</code> is not an array, an array with
+   * <code>param</code> as its single element gets passed to the
+   * logging framework.
+   *
+   * @param t a Throwable that is associated with the log record, or
+   * <code>null</code> if the log message is not associated with a
+   * Throwable.
+   */
+  private static void log(Level level, String msg, Object param, Throwable t)
+  {
+    LogRecord rec;
+
+    // Return quickly if no log message will be produced.
+    if (!LOGGER.isLoggable(level))
+      return;
+
+    rec = new LogRecord(level, msg);
+    if (param != null && param.getClass().isArray())
+      rec.setParameters((Object[]) param);
+    else
+      rec.setParameters(new Object[] { param });
+
+    rec.setThrown(t);
+
+    // While java.util.logging can sometimes infer the class and
+    // method of the caller, this automatic inference is not reliable
+    // on highly optimizing VMs. Also, log messages make more sense to
+    // developers when they display a public method in a public class;
+    // otherwise, they might feel tempted to figure out the internals
+    // of ServiceFactory in order to understand the problem.
+    rec.setSourceClassName(ServiceFactory.class.getName());
+    rec.setSourceMethodName("lookupProviders");
+
+    LOGGER.log(rec);
+  }
+}
diff --git a/libjava/gnu/classpath/ServiceProviderLoadingAction.java b/libjava/gnu/classpath/ServiceProviderLoadingAction.java
new file mode 100644 (file)
index 0000000..4832c97
--- /dev/null
@@ -0,0 +1,149 @@
+/* ServiceProviderLoadingAction.java -- Action for loading plug-in services.
+   Copyright (C) 2004  Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.classpath;
+
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * A privileged action for creating a new instance of a service
+ * provider.
+ *
+ * <p>Class loading and instantiation is encapsulated in a
+ * <code>PriviledgedAction</code> in order to restrict the loaded
+ * service providers to the {@link java.security.AccessControlContext}
+ * that was active when {@link
+ * gnu.classpath.ServiceFactory#lookupProviders} was called, even
+ * though the actual loading is delayed to the time when the provider
+ * is actually needed.
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+final class ServiceProviderLoadingAction
+  implements PrivilegedExceptionAction
+{
+  /**
+   * The interface to which the loaded service provider implementation
+   * must conform.  Usually, this is a Java interface type, but it
+   * might also be an abstract class or even a concrete class.
+   */
+  private final Class spi;
+
+
+  /**
+   * The fully qualified name of the class that gets loaded when
+   * this action is executed.
+   */
+  private final String providerName;
+
+
+  /**
+   * The ClassLoader that gets used for loading the service provider
+   * class.
+   */
+  private final ClassLoader loader;
+
+
+  /**
+   * Constructs a privileged action for loading a service provider.
+   *
+   * @param spi the interface to which the loaded service provider
+   * implementation must conform. Usually, this is a Java interface
+   * type, but it might also be an abstract class or even a concrete
+   * superclass.
+   *
+   * @param providerName the fully qualified name of the class that
+   * gets loaded when this action is executed.
+   *
+   * @param loader the ClassLoader that gets used for loading the
+   * service provider class.
+   *
+   * @throws IllegalArgumentException if <code>spi</code>,
+   * <code>providerName</code> or <code>loader</code> is
+   * <code>null</code>.
+   */
+  ServiceProviderLoadingAction(Class spi, String providerName,
+                               ClassLoader loader)
+  {
+    if (spi == null || providerName == null || loader == null)
+      throw new IllegalArgumentException();
+
+    this.spi = spi;
+    this.providerName = providerName;
+    this.loader = loader;
+  }
+
+  
+  /**
+   * Loads an implementation class for a service provider, and creates
+   * a new instance of the loaded class by invoking its public
+   * no-argument constructor.
+   *
+   * @return a new instance of the class whose name was passed as
+   * <code>providerName</code> to the constructor.
+   *
+   * @throws ClassCastException if the service provider does not
+   * implement the <code>spi</code> interface that was passed to the
+   * constructor.
+   *
+   * @throws IllegalAccessException if the service provider class or
+   * its no-argument constructor are not <code>public</code>.
+   *
+   * @throws InstantiationException if the service provider class is
+   * <code>abstract</code>, an interface, a primitive type, an array
+   * class, or void; or if service provider class does not have a
+   * no-argument constructor; or if there some other problem with
+   * creating a new instance of the service provider.
+   */
+  public Object run()
+    throws Exception
+  {
+    Class loadedClass;
+    Object serviceProvider;
+
+    loadedClass = loader.loadClass(providerName);
+    serviceProvider = loadedClass.newInstance();
+
+    // Ensure that the loaded provider is actually implementing
+    // the service provider interface.
+    if (!spi.isInstance(serviceProvider))
+      throw new ClassCastException(spi.getName());
+
+    return serviceProvider;
+  }
+}
diff --git a/libjava/javax/imageio/ImageReader.java b/libjava/javax/imageio/ImageReader.java
new file mode 100644 (file)
index 0000000..75ae9ad
--- /dev/null
@@ -0,0 +1,46 @@
+/* ImageReader.java -- Decodes raster images.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio;
+
+public abstract class ImageReader
+{
+  // FIXME: Incomplete. This class is merely present in order to allow
+  // compilation of the javax.imageio.spi package, for which GNU
+  // Classpath does provide an implementation.
+}
diff --git a/libjava/javax/imageio/ImageTranscoder.java b/libjava/javax/imageio/ImageTranscoder.java
new file mode 100644 (file)
index 0000000..20c6959
--- /dev/null
@@ -0,0 +1,46 @@
+/* ImageTranscoder.java -- Image metadata transcoder.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio;
+
+public interface ImageTranscoder
+{
+  // FIXME: Incomplete. This interface is merely present in order to
+  // allow compilation of the javax.imageio.spi package, for which GNU
+  // Classpath does provide an implementation.
+}
diff --git a/libjava/javax/imageio/ImageWriter.java b/libjava/javax/imageio/ImageWriter.java
new file mode 100644 (file)
index 0000000..7ef60c3
--- /dev/null
@@ -0,0 +1,47 @@
+/* ImageWriter.java -- Encodes raster images.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio;
+
+public abstract class ImageWriter
+  implements ImageTranscoder
+{
+  // FIXME: Incomplete. This class is merely present in order to allow
+  // compilation of the javax.imageio.spi package, for which GNU
+  // Classpath does provide an implementation.
+}
diff --git a/libjava/javax/imageio/package.html b/libjava/javax/imageio/package.html
new file mode 100644 (file)
index 0000000..ed284b9
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in javax.imageio package.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - javax.imageio</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/javax/imageio/spi/IIOServiceProvider.java b/libjava/javax/imageio/spi/IIOServiceProvider.java
new file mode 100644 (file)
index 0000000..bd0a449
--- /dev/null
@@ -0,0 +1,163 @@
+/* IIOServiceProvider.java -- General service provider for image I/O.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio.spi;
+
+import java.util.Locale;
+
+
+/**
+ * An abstract superclass for service providers that perform image I/O.
+ *
+ * @since 1.4
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public abstract class IIOServiceProvider
+  implements RegisterableService
+{
+  /**
+   * The vendor of this service provider, or <code>null</code> if the
+   * subclass constructor did not set this field.
+   *
+   * @see #getVendorName()
+   */
+  protected String vendorName;
+
+
+  /**
+   * The version of this service provider, or <code>null</code> if the
+   * subclass constructor did not set this field.
+   *
+   * @see #getVersion()
+   */
+  protected String version;
+
+
+  /**
+   * Constructs a general <code>IIOServiceProvider</code>, given the
+   * vendor name and a version string.
+   *
+   * @throws IllegalArgumentException if <code>vendorName</code>
+   * or <code>version</code> is <code>null</code>.
+   */
+  public IIOServiceProvider(String vendorName, String version)
+  {
+    if (vendorName == null || version == null)
+      throw new IllegalArgumentException();
+
+    this.vendorName = vendorName;
+    this.version = version;
+  }
+
+
+  /**
+   * Constructs a general <code>IIOServiceProvider</code> without
+   * specifying a vendor name and a version string. The subclass
+   * constructor should set the {@link #vendorName} and {@link
+   * #version} to non-null values.
+   */
+  public IIOServiceProvider()
+  {
+  }
+
+
+  /**
+   * Informs this service provider that it has been registered in a
+   * {@link ServiceRegistry}. If this provider gets registered as an
+   * implementor for several service categories, its
+   * <code>onRegistration</code> method will be called multiple times.
+   * The default implementation does nothing.
+   *
+   * @param registry the registry to which this service provider has
+   * been added.
+   *
+   * @param category the service category for which this provider has
+   * been registered as an implementor.
+   */
+  public void onRegistration(ServiceRegistry registry, Class category)
+  {
+  }
+
+
+  /**
+   * Informs this service provider that it has been de-registered from
+   * a {@link ServiceRegistry}. If this provider had been registered
+   * as an implementor for several service categories, its
+   * <code>onDeregistration</code> method will be called multiple
+   * times. The default implementation does nothing.
+   *
+   * @param registry the registry from which this service provider has
+   * been removed.
+   *
+   * @param category the service category for which this provider has
+   * been registered as an implementor.
+   */
+  public void onDeregistration(ServiceRegistry registry, Class category)
+  {
+  }
+
+
+  /**
+   * Returns the name of the vendor of this service provider.
+   */
+  public String getVendorName()
+  {
+    return vendorName;
+  }
+
+
+  /**
+   * Returns an identifier string for the version of this service
+   * provider.
+   */
+  public String getVersion()
+  {
+    return version;
+  }
+
+
+  /**
+   * Returns a short description of this service provider that can be
+   * presented to a human user.
+   *
+   * @param locale the locale for which the description string should
+   * be localized.
+   */
+  public abstract String getDescription(Locale locale);
+}
diff --git a/libjava/javax/imageio/spi/ImageInputStreamSpi.java b/libjava/javax/imageio/spi/ImageInputStreamSpi.java
new file mode 100644 (file)
index 0000000..b8d5854
--- /dev/null
@@ -0,0 +1,144 @@
+/* ImageInputStreamSpi.java -- Service provider for image input streams.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio.spi;
+
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.stream.ImageInputStream;
+
+
+/**
+ * An abstract superclass for service providers that create
+ * {@linkplain javax.imageio.stream.ImageInputStream image input
+ * streams} for a file, URL, byte array or any other source.
+ *
+ * @since 1.4
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public abstract class ImageInputStreamSpi
+  extends IIOServiceProvider
+{
+  /**
+   * Indicates which kind of input is processable by the streams
+   * created by {@link #createInputStreamInstance(Object)}.
+   */
+  protected Class inputClass;
+
+
+  /**
+   * Constructs a service provider for image input streams, given no
+   * parameters. It is up to the sub-class to set {@link #vendorName},
+   * {@link #version} and {@link #inputClass} to non-null values.
+   */
+  protected ImageInputStreamSpi()
+  {
+  }
+
+
+  /**
+   * Constructs a service provider for image input streams, given the
+   * vendor name and a version string.
+   *
+   * @throws IllegalArgumentException if <code>vendorName</code>
+   * or <code>version</code> is <code>null</code>.
+   */
+  public ImageInputStreamSpi(String vendorName, String version,
+                             Class inputClass)
+  {
+    super(vendorName, version);
+    this.inputClass = inputClass;
+  }
+
+
+  /**
+   * Determines which kind of input is processable by the streams
+   * created by {@link #createInputStreamInstance(Object)}.
+   */
+  public Class getInputClass()
+  {
+    return inputClass;
+  }
+
+
+  /**
+   * Determines whether <code>ImageInputStreams</code> created
+   * by this service provider benefit from using a cache file.
+   *
+   * <p>The default behavior is to return <code>false</code>.
+   *
+   * @return <code>true</code> if the created streams are faster or
+   * need less memory when a cache file is being used;
+   * <code>false</code> if no positive effect results from the cache
+   * file.
+   */
+  public boolean canUseCacheFile()
+  {
+    return false;
+  }
+
+
+  /**
+   * Determines whether <code>ImageInputStreams</code> created
+   * by this service provider require the use of a cache file.
+   *
+   * <p>The default behavior is to return <code>false</code>.
+   *
+   * @return <code>true</code> if the created streams can only work
+   * when a cache file is being used; <code>false</code> if no cache
+   * file is needed.
+   */
+  public boolean needsCacheFile()
+  {
+    return false;
+  }
+
+
+  public abstract ImageInputStream createInputStreamInstance(Object input,
+                                                             boolean useCache,
+                                                             File cacheDir)
+    throws IOException;
+
+
+  public ImageInputStream createInputStreamInstance(Object input)
+    throws IOException
+  {
+    return createInputStreamInstance(input, canUseCacheFile(), null);
+  }
+}
diff --git a/libjava/javax/imageio/spi/ImageOutputStreamSpi.java b/libjava/javax/imageio/spi/ImageOutputStreamSpi.java
new file mode 100644 (file)
index 0000000..aa287c3
--- /dev/null
@@ -0,0 +1,143 @@
+/* ImageOutputStreamSpi.java -- Service provider for image output streams.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio.spi;
+
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.stream.ImageOutputStream;
+
+
+/**
+ * An abstract superclass for service providers that create
+ * {@linkplain javax.imageio.stream.ImageOutputStream image output
+ * streams} for a file, URL, byte array or any other target.
+ *
+ * @since 1.4
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public abstract class ImageOutputStreamSpi
+  extends IIOServiceProvider
+{
+  /**
+   * Indicates which kind of output is produced by the streams
+   * created by {@link #createOutputStreamInstance(Object)}.
+   */
+  protected Class outputClass;
+
+
+  /**
+   * Constructs a service provider for image output streams, given no
+   * parameters. It is up to the sub-class to set {@link #vendorName},
+   * {@link #version} and {@link #outputClass} to non-null values.
+   */
+  protected ImageOutputStreamSpi()
+  {
+  }
+
+
+  /**
+   * Constructs a service provider for image output streams, given the
+   * vendor name, a version string and the kind of producable output.
+   *
+   * @throws IllegalArgumentException if <code>vendorName</code>
+   * or <code>version</code> is <code>null</code>.
+   */
+  public ImageOutputStreamSpi(String vendorName, String version,
+                              Class outputClass)
+  {
+    super(vendorName, version);
+    this.outputClass = outputClass;
+  }
+
+
+  /**
+   * Determines which kind of output is produced by the streams
+   * created by {@link #createOutputStreamInstance(Object)}.
+   */
+  public Class getOutputClass()
+  {
+    return outputClass;
+  }
+
+
+  /**
+   * Determines whether <code>ImageOutputStreams</code> created
+   * by this service provider benefit from using a cache file.
+   *
+   * <p>The default behavior is to return <code>false</code>.
+   *
+   * @return <code>true</code> if the created streams are faster or
+   * need less memory when a cache file is being used;
+   * <code>false</code> if no positive effect results from the cache
+   * file.
+   */
+  public boolean canUseCacheFile()
+  {
+    return false;
+  }
+
+
+  /**
+   * Determines whether <code>ImageOutputStreams</code> created
+   * by this service provider require the use of a cache file.
+   *
+   * <p>The default behavior is to return <code>false</code>.
+   *
+   * @return <code>true</code> if the created streams can only work
+   * when a cache file is being used; <code>false</code> if no cache
+   * file is needed.
+   */
+  public boolean needsCacheFile()
+  {
+    return false;
+  }
+
+
+  public abstract ImageOutputStream createOutputStreamInstance(
+    Object output, boolean useCache, File cacheDir)
+    throws IOException;
+
+
+  public ImageOutputStream createOutputStreamInstance(Object output)
+    throws IOException
+  {
+    return createOutputStreamInstance(output, canUseCacheFile(), null);
+  }
+}
diff --git a/libjava/javax/imageio/spi/ImageReaderWriterSpi.java b/libjava/javax/imageio/spi/ImageReaderWriterSpi.java
new file mode 100644 (file)
index 0000000..33de165
--- /dev/null
@@ -0,0 +1,425 @@
+/* ImageReaderWriterSpi.java -- Superclass for image reader and writer spis.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio.spi;
+
+
+/**
+ * An abstract superclass that contains the common parts of {@link
+ * javax.imageio.spi.ImageReaderSpi} and {@link
+ * javax.imageio.spi.ImageWriterSpi}.
+ *
+ * @since 1.4
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public abstract class ImageReaderWriterSpi
+  extends IIOServiceProvider
+{
+  /**
+   * The human-readable, localized names of the supported image
+   * formats. This value should be non-<code>null</code> after
+   * construction.
+   *
+   * @see #getFormatNames()
+   */
+  protected String[] names;
+
+
+  /**
+   * The file suffixes of the supported image formats. This value
+   * should be non-<code>null</code> after construction.
+   *
+   * @see #getFileSuffixes()
+   */
+  protected String[] suffixes;
+
+
+  /**
+   * The MIME types of the supported image formats.  This value
+   * should be non-<code>null</code> after construction.
+   *
+   * @see #getMIMETypes()
+   */
+  protected String[] MIMETypes;
+
+
+  /**
+   * The fully qualified name of the class that implements the {@link
+   * javax.imageio.ImageReader} or {@link javax.imageio.ImageWriter}
+   * interface.  This value should be non-<code>null</code> after
+   * construction.
+   *
+   * @see #getPluginClassName()
+   */
+  protected String pluginClassName;
+
+
+  /**
+   * Indicates whether the per-stream {@linkplain
+   * javax.imageio.metadata.IIOMetadata metadata objects} associated
+   * with this plug-in support format
+   * <code>&#x201c;javax_imageio_1.0&#x201d;</code> in their
+   * <code>getAsTree</code> and <code>setAsTree</code> methods.
+   *
+   * @see #isStandardStreamMetadataFormatSupported()
+   */
+  protected boolean supportsStandardStreamMetadataFormat;
+
+
+  /**
+   * The name of the format that allows encoding all stream metadata
+   * without loss, or <code>null</code> if this plug-in does not
+   * provide a format that preserves all stream metadata.
+   */
+  protected String nativeStreamMetadataFormatName;
+
+  protected String nativeStreamMetadataFormatClassName;
+
+
+  /**
+   * The names of additional formats for encoding stream metadata,
+   * other than the {@linkplain
+   * #isStandardStreamMetadataFormatSupported() standard} and the
+   * {@linkplain #getNativeStreamMetadataFormatName() native} formats,
+   * or <code>null</code> if this plug-in does not provide any extra
+   * formats.
+   */
+  protected String[] extraStreamMetadataFormatNames;
+
+
+  protected String[] extraStreamMetadataFormatClassNames;
+
+
+  /**
+   * Indicates whether the per-image {@linkplain
+   * javax.imageio.metadata.IIOMetadata metadata objects} associated
+   * with this plug-in support format
+   * <code>&#x201c;javax_imageio_1.0&#x201d;</code> in their
+   * <code>getAsTree</code> and <code>setAsTree</code> methods.
+   *
+   * @see #isStandardImageMetadataFormatSupported()
+   */
+  protected boolean supportsStandardImageMetadataFormat;
+
+
+  /**
+   * The name of the format that allows encoding all image metadata
+   * without loss, or <code>null</code> if this plug-in does not
+   * provide a format that preserves all image metadata.
+   */
+  protected String nativeImageMetadataFormatName;
+
+  protected String nativeImageMetadataFormatClassName;
+
+
+  /**
+   * The names of additional formats for encoding image metadata,
+   * other than the {@linkplain
+   * #isStandardImageMetadataFormatSupported() standard} and the
+   * {@linkplain #getNativeImageMetadataFormatName() native} formats,
+   * or <code>null</code> if this plug-in does not provide any extra
+   * formats.
+   */
+  protected String[] extraImageMetadataFormatNames;
+
+
+  protected String[] extraImageMetadataFormatClassNames;
+
+
+  /**
+   * Constructs an <code>ImageReaderWriteSpi</code> instance, without
+   * specifying a number of parameters. Constructors of concrete
+   * subclasses must ensure that they set all inherited fields to
+   * meaningful values.
+   */
+  protected ImageReaderWriterSpi()
+  {
+  }
+
+
+  /**
+   * Constructs an <code>ImageReaderWriteSpi</code> instance,
+   * specifying a number of parameters.
+   *
+   * @param names the human-readable, localized names of the supported
+   * image formats, for example <code>[&#x201c;Tagged Image File
+   * Format&#x201d;, &#x201c;Portable Network
+   * Graphics&#x201d;]</code>.
+   *
+   * @param suffixes the file suffixes of the supported image formats,
+   * for example <code>[&#x201c;tiff&#x201d;, &#x201c;tif&#x201d;,
+   * &#x201c;png&#x201d;]</code>.
+   *
+   * @param MIMETypes the MIME types of the supported image formats,
+   * for example <code>[&#x201c;image/tiff&#x201d;,
+   * &#x201c;image/png&#x201d;]</code>.
+   *
+   * @param pluginClassName the fully qualified name of the class that
+   * implements the {@link javax.imageio.ImageReader} or {@link
+   * javax.imageio.ImageWriter} interface.
+   *
+   * @param supportsStandardStreamMetadataFormat whether the
+   * per-stream {@linkplain javax.imageio.metadata.IIOMetadata
+   * metadata objects} associated with this plug-in support format
+   * <code>&#x201c;javax_imageio_1.0&#x201d;</code> in their
+   * <code>getAsTree</code> and <code>setAsTree</code> methods.
+   *
+   * @param nativeStreamMetadataFormatName the name of the format that
+   * allows encoding all stream metadata without loss, or
+   * <code>null</code> if this plug-in does not provide a format that
+   * preserves all stream metadata.
+   *
+   * @param extraStreamMetadataFormatNames the names of additional
+   * formats for encoding stream metadata, other than the {@linkplain
+   * #isStandardStreamMetadataFormatSupported() standard} and the
+   * {@linkplain #getNativeStreamMetadataFormatName() native} formats,
+   * or <code>null</code> if this plug-in does not provide any extra
+   * formats.
+   *
+   * @param supportsStandardImageMetadataFormat whether the per-image
+   * {@linkplain javax.imageio.metadata.IIOMetadata metadata objects}
+   * associated with this plug-in support format
+   * <code>&#x201c;javax_imageio_1.0&#x201d;</code> in their
+   * <code>getAsTree</code> and <code>setAsTree</code> methods.
+   *
+   * @param nativeImageMetadataFormatName the name of the format that
+   * allows encoding all image metadata without loss, or
+   * <code>null</code> if this plug-in does not provide a format that
+   * preserves all image metadata.
+   *
+   * @param extraImageMetadataFormatNames the names of additional
+   * formats for encoding image metadata, other than the {@linkplain
+   * #isStandardImageMetadataFormatSupported() standard} and the
+   * {@linkplain #getNativeImageMetadataFormatName() native} formats,
+   * or <code>null</code> if this plug-in does not provide any extra
+   * formats.
+   *
+   * @throws IllegalArgumentException if <code>vendorName</code>
+   * or <code>version</code> is <code>null</code>.
+   */
+  public ImageReaderWriterSpi(String vendorName, String version,
+                              String[] names, String[] suffixes,
+                              String[] MIMETypes, String pluginClassName,
+                              boolean supportsStandardStreamMetadataFormat,
+                              String nativeStreamMetadataFormatName,
+                              String nativeStreamMetadataFormatClassName,
+                              String[] extraStreamMetadataFormatNames,
+                              String[] extraStreamMetadataFormatClassNames,
+                              boolean supportsStandardImageMetadataFormat,
+                              String nativeImageMetadataFormatName,
+                              String nativeImageMetadataFormatClassName,
+                              String[] extraImageMetadataFormatNames,
+                              String[] extraImageMetadataFormatClassNames)
+  {
+    /* The inherited constructor will throw IllegalArgumentException
+     * if one of its arguments is null.
+     */
+    super(vendorName, version);
+
+    if (names == null || names.length == 0 || pluginClassName == null)
+      throw new IllegalArgumentException();
+
+    this.names = names;
+    this.suffixes = suffixes;
+    this.MIMETypes = MIMETypes;
+    this.pluginClassName = pluginClassName;
+
+    this.supportsStandardStreamMetadataFormat
+      = supportsStandardStreamMetadataFormat;
+
+    this.nativeStreamMetadataFormatName
+      = nativeStreamMetadataFormatName;
+
+    this.nativeStreamMetadataFormatClassName
+      = nativeStreamMetadataFormatClassName;
+
+    this.extraStreamMetadataFormatNames
+      = extraStreamMetadataFormatNames;
+
+    this.extraStreamMetadataFormatClassNames
+      = extraStreamMetadataFormatClassNames;
+
+    this.supportsStandardImageMetadataFormat
+      = supportsStandardImageMetadataFormat;
+
+    this.nativeImageMetadataFormatName
+      = nativeImageMetadataFormatName;
+
+    this.nativeImageMetadataFormatClassName
+      = nativeImageMetadataFormatClassName;
+
+    this.extraImageMetadataFormatNames
+      = extraImageMetadataFormatNames;
+
+    this.extraImageMetadataFormatClassNames
+      = extraImageMetadataFormatClassNames;
+  }
+
+
+  /**
+   * Returns the human-readable, localized names of the supported
+   * image formats. For example, a plug-in might return an array with
+   * the elements <code>[&#x201c;Tagged Image File Format&#x201d;,
+   * &#x201c;Portable Network Graphics&#x201d;]</code>.
+   */
+  public String[] getFormatNames()
+  {
+    return (String[]) names.clone();
+  }
+
+
+  /**
+   * Returns the file suffixes of the supported image formats, for
+   * example <code>[&#x201c;tiff&#x201d;, &#x201c;tif&#x201d;,
+   * &#x201c;png&#x201d;]</code>.
+   */
+  public String[] getFileSuffixes()
+  {
+    return suffixes;
+  }
+
+
+  /**
+   * Returns the MIME types of the supported image formats, for
+   * example <code>[&#x201c;image/tiff&#x201d;,
+   * &#x201c;image/png&#x201d;]</code>.
+   *
+   * @return an array of MIME type strings, or <code>null</code> if
+   * none of the supported formats has an associated MIME type.
+   */
+  public String[] getMIMETypes()
+  {
+    return MIMETypes;
+  }
+
+
+  /**
+   * Returns the fully qualified name of the class that implements the
+   * {@link javax.imageio.ImageReader} or {@link
+   * javax.imageio.ImageWriter} interface.
+   */
+  public String getPluginClassName()
+  {
+    return pluginClassName;
+  }
+
+
+  /**
+   * Returns whether the per-stream {@linkplain
+   * javax.imageio.metadata.IIOMetadata metadata objects} associated
+   * with this plug-in support format
+   * <code>&#x201c;javax_imageio_1.0&#x201d;</code> in their
+   * <code>getAsTree</code> and <code>setAsTree</code> methods.
+   */
+  public boolean isStandardStreamMetadataFormatSupported()
+  {
+    return supportsStandardStreamMetadataFormat;
+  }
+
+
+  /**
+   * Returns the name of the format that allows encoding all stream
+   * metadata without loss, or <code>null</code> if this plug-in does
+   * not provide a format that preserves all stream metadata.
+   *
+   * @see #getNativeImageMetadataFormatName()
+   */
+  public String getNativeStreamMetadataFormatName()
+  {
+    return nativeStreamMetadataFormatName;
+  }
+
+
+  /**
+   * Returns the names of additional formats for encoding stream
+   * metadata, other than the {@linkplain
+   * #isStandardStreamMetadataFormatSupported() standard} and the
+   * {@linkplain #getNativeStreamMetadataFormatName() native} formats,
+   * or <code>null</code> if this plug-in does not provide any extra
+   * formats.
+   *
+   * @see #getExtraImageMetadataFormatNames()
+   */
+  public String[] getExtraStreamMetadataFormatNames()
+  {
+    return extraStreamMetadataFormatNames;
+  }
+
+
+  /**
+   * Returns whether the per-image {@linkplain
+   * javax.imageio.metadata.IIOMetadata metadata objects} associated
+   * with this plug-in support format
+   * <code>&#x201c;javax_imageio_1.0&#x201d;</code> in their
+   * <code>getAsTree</code> and <code>setAsTree</code> methods.
+   */
+  public boolean isStandardImageMetadataFormatSupported()
+  {
+    return supportsStandardImageMetadataFormat;
+  }
+
+
+  /**
+   * Returns the name of the format that allows encoding all image
+   * metadata without loss, or <code>null</code> if this plug-in does
+   * not provide a format that preserves all image metadata.
+   *
+   * @see #getNativeStreamMetadataFormatName()
+   */
+  public String getNativeImageMetadataFormatName()
+  {
+    return nativeImageMetadataFormatName;
+  }
+
+
+  /**
+   * Returns the names of additional formats for encoding image
+   * metadata, other than the {@linkplain
+   * #isStandardImageMetadataFormatSupported() standard} and the
+   * {@linkplain #getNativeImageMetadataFormatName() native} formats,
+   * or <code>null</code> if this plug-in does not provide any extra
+   * formats.
+   *
+   * @see #getExtraStreamMetadataFormatNames()
+   */
+  public String[] getExtraImageMetadataFormatNames()
+  {
+    return extraImageMetadataFormatNames;
+  }
+}
diff --git a/libjava/javax/imageio/spi/ImageTranscoderSpi.java b/libjava/javax/imageio/spi/ImageTranscoderSpi.java
new file mode 100644 (file)
index 0000000..85ca77d
--- /dev/null
@@ -0,0 +1,84 @@
+/* ImageTranscoderSpi.java -- Factory for image metadata transcoders.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio.spi;
+
+import javax.imageio.ImageTranscoder;
+
+
+/**
+ * An abstract superclass for service providers that create
+ * {@linkplain javax.imageio.ImageTranscoder image metadata
+ * transcoders}.
+ *
+ * @since 1.4
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public abstract class ImageTranscoderSpi
+  extends IIOServiceProvider
+{
+  /**
+   * Constructs a service provider for image metadata transcoders,
+   * given no parameters. It is up to the sub-class to set {@link
+   * #vendorName} and {@link #version} to non-null values.
+   */
+  protected ImageTranscoderSpi()
+  {
+  }
+
+
+  /**
+   * Constructs a service provider for image metadata transcoders,
+   * given the vendor name and a version string.
+   *
+   * @throws IllegalArgumentException if <code>vendorName</code>
+   * or <code>version</code> is <code>null</code>.
+   */
+  public ImageTranscoderSpi(String vendorName, String version)
+  {
+    super(vendorName, version);
+  }
+
+
+  public abstract String getReaderServiceProviderName();
+
+  public abstract String getWriterServiceProviderName();
+
+  public abstract ImageTranscoder createTranscoderInstance();
+}
diff --git a/libjava/javax/imageio/spi/RegisterableService.java b/libjava/javax/imageio/spi/RegisterableService.java
new file mode 100644 (file)
index 0000000..40cb05f
--- /dev/null
@@ -0,0 +1,83 @@
+/* RegisterableService.java -- An interface for service providers.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio.spi;
+
+
+/**
+ * An interface which service providers may optionally implement in
+ * order to get notified when they are added or removed from a {@link
+ * ServiceRegistry}.
+ *
+ * @since 1.4
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public interface RegisterableService
+{
+  /**
+   * Informs this service provider that it has been registered in a
+   * {@link ServiceRegistry}. If this provider gets registered as an
+   * implementor for several service categories, its
+   * <code>onRegistration</code> method will be called multiple times.
+   *
+   * @param registry the registry to which this service provider has
+   * been added.
+   *
+   * @param category the service category for which this provider has
+   * been registered as an implementor.
+   */
+  void onRegistration(ServiceRegistry registry, Class category);
+
+
+  /**
+   * Informs this service provider that it has been de-registered from
+   * a {@link ServiceRegistry}. If this provider had been registered
+   * as an implementor for several service categories, its
+   * <code>onDeregistration</code> method will be called multiple
+   * times.
+   *
+   * @param registry the registry from which this service provider has
+   * been removed.
+   *
+   * @param category the service category for which this provider has
+   * been registered as an implementor.
+   */
+  void onDeregistration(ServiceRegistry registry, Class category);
+}
+
diff --git a/libjava/javax/imageio/spi/ServiceRegistry.java b/libjava/javax/imageio/spi/ServiceRegistry.java
new file mode 100644 (file)
index 0000000..c41e1b5
--- /dev/null
@@ -0,0 +1,948 @@
+/* ServiceRegistry.java -- A simple registry for service providers.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio.spi;
+
+import java.util.*;
+import gnu.classpath.ServiceFactory;
+
+
+/**
+ * A registry for service providers.
+ *
+ * @since 1.4
+ *
+ * @author <a href="mailto:konqueror@gmx.de">Michael Koch</a>
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public class ServiceRegistry
+{
+  /**
+   * The service categories of this registry.
+   *
+   * <p>Note that we expect that only very few categories will
+   * typically be used with a registry. The most common case will be
+   * one, it seems unlikely that any registry would contain more than
+   * five or six categories. Therefore, we intentionally avoid the
+   * overhead of a HashMap.
+   *
+   * @see #providers
+   */
+  private final Class[] categories;
+
+
+  /**
+   * The registered providers for each service category, indexed by
+   * the same index as the {@link #categories} array. If no provider
+   * is registered for a category, the array entry will be
+   * <code>null</code>.
+   *
+   * <p>Note that we expect that only very few providers will
+   * typically be registered for a category. The most common case will
+   * be one or two. Therefore, we intentionally avoid the overhead of
+   * a HashMap.
+   */
+  private final LinkedList[] providers;
+
+
+  /**
+   * The ordring constaints for each service category, indexed by the
+   * same index as the {@link #categories} array. The constraints for
+   * a service category are stored as a <code>Map&lt;Object,
+   * Set&lt;Object&gt;&gt;</code>, where the Map&#x2019;s values are
+   * those providers that need to come after the key.  If no
+   * constraints are imposed on the providers of a category, the array
+   * entry will be <code>null</code>. If no constraints have been set
+   * whatsoever, <code>constraints</code> will be <code>null</code>.
+   *
+   * <p>Note that we expect that only very few constraints will
+   * typically be imposed on a category. The most common case will
+   * be zero.
+   */
+  private IdentityHashMap[] constraints;
+
+  
+  /**
+   * Constructs a <code>ServiceRegistry</code> for the specified
+   * service categories.
+   *
+   * @throws IllegalArgumentException if <code>categories</code> is
+   * <code>null</code>, or if its {@link Iterator#next()} method
+   * returns <code>null</code>.
+   *
+   * @throws ClassCastException if <code>categories</code> does not
+   * iterate over instances of {@link java.lang.Class}.
+   */
+  public ServiceRegistry(Iterator categories)
+  {
+    ArrayList cats = new ArrayList(/* expected size */ 10);
+
+    if (categories == null)
+      throw new IllegalArgumentException();
+
+    while (categories.hasNext())
+      {
+        Class cat = (Class) categories.next();
+        if (cat == null)
+          throw new IllegalArgumentException();
+        cats.add(cat);
+      }
+
+    int numCats = cats.size();
+    this.categories = (Class[]) cats.toArray(new Class[numCats]);
+    this.providers = new LinkedList[numCats];
+  }
+
+
+  /**
+   * Finds service providers that are implementing the specified
+   * Service Provider Interface.
+   *
+   * <p><b>On-demand loading:</b> Loading and initializing service
+   * providers is delayed as much as possible. The rationale is that
+   * typical clients will iterate through the set of installed service
+   * providers until one is found that matches some criteria (like
+   * supported formats, or quality of service). In such scenarios, it
+   * might make sense to install only the frequently needed service
+   * providers on the local machine. More exotic providers can be put
+   * onto a server; the server will only be contacted when no suitable
+   * service could be found locally.
+   *
+   * <p><b>Security considerations:</b> Any loaded service providers
+   * are loaded through the specified ClassLoader, or the system
+   * ClassLoader if <code>classLoader</code> is
+   * <code>null</code>. When <code>lookupProviders</code> is called,
+   * the current {@link java.security.AccessControlContext} gets
+   * recorded. This captured security context will determine the
+   * permissions when services get loaded via the <code>next()</code>
+   * method of the returned <code>Iterator</code>.
+   *
+   * @param spi the service provider interface which must be
+   * implemented by any loaded service providers.
+   *
+   * @param loader the class loader that will be used to load the
+   * service providers, or <code>null</code> for the system class
+   * loader. For using the context class loader, see {@link
+   * #lookupProviders(Class)}.
+   *
+   * @return an iterator over instances of <code>spi</code>.
+   *
+   * @throws IllegalArgumentException if <code>spi</code> is
+   * <code>null</code>.
+   */
+  public static Iterator lookupProviders(Class spi,
+                                         ClassLoader loader)
+  {
+    return ServiceFactory.lookupProviders(spi, loader);
+  }
+
+
+  /**
+   * Finds service providers that are implementing the specified
+   * Service Provider Interface, using the context class loader
+   * for loading providers.
+   *
+   * @param spi the service provider interface which must be
+   * implemented by any loaded service providers.
+   *
+   * @return an iterator over instances of <code>spi</code>.
+   *
+   * @throws IllegalArgumentException if <code>spi</code> is
+   * <code>null</code>.
+   *
+   * @see #lookupProviders(Class, ClassLoader)
+   */
+  public static Iterator lookupProviders(Class spi)
+  {
+    return ServiceFactory.lookupProviders(spi);
+  }
+
+
+  /**
+   * Returns an iterator over all service categories.
+   *
+   * @return an unmodifiable {@link
+   * java.util.Iterator}&lt;{@link java.lang.Class}&gt;.
+   */
+  public Iterator getCategories()
+  {
+    return new Iterator()
+      {
+        int index = -1;
+
+        public boolean hasNext()
+        {
+          return index < categories.length - 1;
+        }
+
+        public Object next()
+        {
+          if (!hasNext())
+            throw new NoSuchElementException();
+
+          return categories[++index];
+        }
+
+        public void remove()
+        {
+          throw new UnsupportedOperationException();
+        }
+      };
+  }
+
+
+  /**
+   * Registers a provider for a service category which is specified by
+   * the class-internal category ID.
+   *
+   * @param provider the service provider to be registered.
+   *
+   * @param cat the service category, which is identified by an index
+   * into the {@link #categories} array.
+   *
+   * @return <code>true</code> if <code>provider</code> is the first
+   * provider that gets registered for the specified service category;
+   * <code>false</code> if other providers have already been
+   * registered for the same servide category.
+   *
+   * @throws IllegalArgumentException if <code>provider</code> is
+   * <code>null</code>.
+   *
+   * @throws ClassCastException if <code>provider</code> does not
+   * implement the specified service provider interface.
+   */
+  private synchronized boolean registerServiceProvider(Object provider,
+                                                       int cat)
+  {
+    LinkedList provs;
+    boolean result;
+    Class category;
+
+    if (provider == null)
+      throw new IllegalArgumentException();
+
+    category = categories[cat];
+    if (!category.isInstance(provider))
+      throw new ClassCastException(category.getName());
+
+    provs = providers[cat];
+    if (provs == null)
+    {
+      result = true;
+      provs = providers[cat] = new LinkedList();
+    }
+    else
+      result = false;
+
+    provs.add(provider);
+    if (provider instanceof RegisterableService)
+      ((RegisterableService) provider).onRegistration(this, category);
+
+    return result;
+  }
+
+
+  /**
+   * Registers a provider for the specified service category.
+   *
+   * <p>If <code>provider</code> implements the {@link
+   * RegisterableService} interface, its {@link
+   * RegisterableService#onRegistration onRegistration} method is
+   * invoked in order to inform the provider about the addition to
+   * this registry.
+   *
+   * @param provider the service provider to be registered.
+   *
+   * @param category the service category under which
+   * <code>provider</code> shall be registered.
+   *
+   * @return <code>true</code> if <code>provider</code> is the first
+   * provider that gets registered for the specified service category;
+   * <code>false</code> if other providers have already been
+   * registered for the same servide category.
+   *
+   * @throws IllegalArgumentException if <code>provider</code> is
+   * <code>null</code>, or if <code>category</code> is not among the
+   * categories passed to the {@linkplain #ServiceRegistry(Iterator)
+   * constructor} of this ServiceRegistry.
+   *
+   * @throws ClassCastException if <code>provider</code> does not
+   * implement <code>category</code>.
+   */
+  public synchronized boolean registerServiceProvider(Object provider,
+                                                      Class category)
+  {
+    for (int i = 0; i < categories.length; i++)
+      if (categories[i] == category)
+        return registerServiceProvider(provider, i);
+    throw new IllegalArgumentException();
+  }
+
+
+  /**
+   * Registers a provider under all service categories it
+   * implements.
+   *
+   * <p>If <code>provider</code> implements the {@link
+   * RegisterableService} interface, its {@link
+   * RegisterableService#onRegistration onRegistration} method is
+   * invoked in order to inform the provider about the addition to
+   * this registry. If <code>provider</code> implements several
+   * service categories, <code>onRegistration</code> gets called
+   * multiple times.
+   *
+   * @param provider the service provider to be registered.
+   *
+   * @throws IllegalArgumentException if <code>provider</code> is
+   * <code>null</code>, or if <code>provider</code> does not implement
+   * any of the service categories passed to the {@linkplain
+   * #ServiceRegistry(Iterator) constructor} of this ServiceRegistry.
+   */
+  public synchronized void registerServiceProvider(Object provider)
+  {
+    boolean ok = false;
+
+    if (provider == null)
+      throw new IllegalArgumentException();
+
+    for (int i = 0; i < categories.length; i++)
+      if (categories[i].isInstance(provider))
+        {
+          ok = true;
+          registerServiceProvider(provider, i);
+        }
+
+    if (!ok)
+      throw new IllegalArgumentException();
+  }
+
+
+  /**
+   * Registers a number of providers under all service categories they
+   * implement.
+   *
+   * <p>If a provider implements the {@link RegisterableService}
+   * interface, its {@link RegisterableService#onRegistration
+   * onRegistration} method is invoked in order to inform the provider
+   * about the addition to this registry. If <code>provider</code>
+   * implements several service categories,
+   * <code>onRegistration</code> gets called multiple times.
+   *
+   * @throws IllegalArgumentException if <code>providers</code> is
+   * <code>null</code>, if any iterated provider is <code>null</code>,
+   * or if some iterated provider does not implement any of the
+   * service categories passed to the {@linkplain
+   * #ServiceRegistry(Iterator) constructor} of this
+   * <code>ServiceRegistry</code>.
+   */
+  public synchronized void registerServiceProviders(Iterator providers)
+  {
+    if (providers == null)
+      throw new IllegalArgumentException();
+
+    while (providers.hasNext())
+      registerServiceProvider(providers.next());
+  }
+
+
+  /**
+   * De-registers a provider for a service category which is specified
+   * by the class-internal category ID.
+   *
+   * @param provider the service provider to be registered.
+   *
+   * @param cat the service category, which is identified by an index
+   * into the {@link #categories} array.
+   *
+   * @return <code>true</code> if <code>provider</code> was previously
+   * registered for the specified service category; <code>false</code>
+   * if if the provider had not been registered.
+   *
+   * @throws IllegalArgumentException if <code>provider</code> is
+   * <code>null</code>.
+   *
+   * @throws ClassCastException if <code>provider</code> does not
+   * implement the specified service provider interface.
+   */
+  private synchronized boolean deregisterServiceProvider(Object provider,
+                                                         int cat)
+  {
+    LinkedList provs;
+    boolean result;
+    Class category;
+
+    if (provider == null)
+      throw new IllegalArgumentException();
+
+    category = categories[cat];
+    if (!category.isInstance(provider))
+      throw new ClassCastException(category.getName());
+
+    provs = providers[cat];
+    if (provs == null)
+      return false;
+
+    result = provs.remove(provider);
+    if (provs.isEmpty())
+      providers[cat] = null;
+
+    if (result && (provider instanceof RegisterableService))
+      ((RegisterableService) provider).onDeregistration(this, category);
+
+    return result;
+  }
+
+
+  /**
+   * De-registers a provider for the specified service category.
+   *
+   * <p>If <code>provider</code> implements the {@link
+   * RegisterableService} interface, its {@link
+   * RegisterableService#onDeregistration onDeregistration} method is
+   * invoked in order to inform the provider about the removal from
+   * this registry.
+   *
+   * @param provider the service provider to be de-registered.
+   *
+   * @param category the service category from which
+   * <code>provider</code> shall be de-registered.
+   *
+   * @return <code>true</code> if <code>provider</code> was previously
+   * registered for the specified service category; <code>false</code>
+   * if if the provider had not been registered.
+   *
+   * @throws IllegalArgumentException if <code>provider</code> is
+   * <code>null</code>, or if <code>category</code> is not among the
+   * categories passed to the {@linkplain #ServiceRegistry(Iterator)
+   * constructor} of this ServiceRegistry.
+   *
+   * @throws ClassCastException if <code>provider</code> does not
+   * implement <code>category</code>.
+   */
+  public synchronized boolean deregisterServiceProvider(Object provider,
+                                                        Class category)
+  {
+    for (int i = 0; i < categories.length; i++)
+      if (categories[i] == category)
+        return deregisterServiceProvider(provider, i);
+    throw new IllegalArgumentException();
+  }
+  
+  
+  /**
+   * De-registers a provider from all service categories it
+   * implements.
+   *
+   * <p>If <code>provider</code> implements the {@link
+   * RegisterableService} interface, its {@link
+   * RegisterableService#onDeregistration onDeregistration} method is
+   * invoked in order to inform the provider about the removal from
+   * this registry. If <code>provider</code> implements several
+   * service categories, <code>onDeregistration</code> gets called
+   * multiple times.
+   *
+   * @param provider the service provider to be de-registered.
+   *
+   * @throws IllegalArgumentException if <code>provider</code> is
+   * <code>null</code>, or if <code>provider</code> does not implement
+   * any of the service categories passed to the {@linkplain
+   * #ServiceRegistry(Iterator) constructor} of this
+   * <code>ServiceRegistry</code>.
+   */
+  public synchronized void deregisterServiceProvider(Object provider)
+  {
+    boolean ok = false;
+
+    if (provider == null)
+      throw new IllegalArgumentException();
+
+    for (int i = 0; i < categories.length; i++)
+      if (categories[i].isInstance(provider))
+        {
+          ok = true;
+          deregisterServiceProvider(provider, i);
+        }
+
+    if (!ok)
+      throw new IllegalArgumentException();
+  }
+
+
+  /**
+   * De-registers all providers which have been registered for the
+   * specified service category.
+   *
+   * <p>If a provider implements the {@link RegisterableService}
+   * interface, its {@link RegisterableService#onDeregistration
+   * onDeregistration} method is invoked in order to inform the
+   * provider about the removal from this registry. If the provider
+   * implements several service categories,
+   * <code>onDeregistration</code> gets called multiple times.
+   *
+   * @param category the category whose registered providers will be
+   * de-registered.
+   *
+   * @throws IllegalArgumentException if <code>category</code> is not
+   * among the categories passed to the {@linkplain
+   * #ServiceRegistry(Iterator) constructor} of this
+   * <code>ServiceRegistry</code>.
+   */
+  public synchronized void deregisterAll(Class category)
+  {
+    boolean ok = false;
+
+    for (int i = 0; i < categories.length; i++)
+      {
+        if (categories[i] != category)
+          continue;
+
+        ok = true;
+        while (providers[i] != null)
+          deregisterServiceProvider(providers[i].get(0), i);
+      }
+
+    if (!ok)
+      throw new IllegalArgumentException();
+  }
+
+
+  /**
+   * De-registers all service providers.
+   *
+   * <p>If a provider implements the {@link RegisterableService}
+   * interface, its {@link RegisterableService#onDeregistration
+   * onDeregistration} method is invoked in order to inform the
+   * provider about the removal from this registry. If the provider
+   * implements several service categories,
+   * <code>onDeregistration</code> gets called multiple times.
+   */
+  public synchronized void deregisterAll()
+  {
+    for (int i = 0; i < categories.length; i++)
+      while (providers[i] != null)
+        deregisterServiceProvider(providers[i].get(0), i);
+  }
+
+
+  /**
+   * Called by the Virtual Machine when it detects that this
+   * <code>ServiceRegistry</code> has become garbage. De-registers all
+   * service providers, which will cause those that implement {@link
+   * RegisterableService} to receive a {@link
+   * RegisterableService#onDeregistration onDeregistration}
+   * notification.
+   */
+  public void finalize()
+    throws Throwable
+  {
+    super.finalize();
+    deregisterAll();
+  }
+
+
+  /**
+   * Determines whether a provider has been registered with this
+   * registry.
+   *
+   * @return <code>true</code> if <code>provider</code> has been
+   * registered under any service category; <code>false</code> if
+   * it is not registered.
+   *
+   * @throws IllegalArgumentException if <code>provider</code> is
+   * <code>null</code>.
+   */
+  public synchronized boolean contains(Object provider)
+  {
+    if (provider == null)
+      throw new IllegalArgumentException();
+
+    // Note that contains is rather unlikely to be ever called,
+    // so it would be wasteful to keep a special data structure
+    // (such as a HashSet) for making it a fast operation.
+    for (int i = 0; i < providers.length; i++)
+      {
+        // If provider does not implement categories[i],
+        // it would not have been possible to register it there.
+        // In that case, it would be pointless to look there.
+        if (!categories[i].isInstance(provider))
+          continue;
+
+        // But if the list of registered providers contains provider,
+        // we have found it.
+        LinkedList p = providers[i];
+        if (p != null && p.contains(provider))
+          return true;
+      }
+
+    return false;
+  }
+
+
+  /**
+   * Returns the index in {@link #categories} occupied by the
+   * specified service category.
+   *
+   * @throws IllegalArgumentException if <code>category</code> is not
+   * among the categories passed to the {@linkplain
+   * #ServiceRegistry(Iterator) constructor} of this ServiceRegistry.
+   */
+  private int getCategoryID(Class category)
+  {
+    for (int i = 0; i < categories.length; i++)
+      if (categories[i] == category)
+        return i;
+
+    throw new IllegalArgumentException();
+  }
+
+
+  /**
+   * Retrieves all providers that have been registered for the
+   * specified service category.
+   *
+   * @param category the service category whose providers are
+   * to be retrieved.
+   *
+   * @param useOrdering <code>true</code> in order to retrieve the
+   * providers in an order imposed by the {@linkplain #setOrdering
+   * ordering constraints}; <code>false</code> in order to retrieve
+   * the providers in any order.
+   *
+   * @throws IllegalArgumentException if <code>category</code> is not
+   * among the categories passed to the {@linkplain
+   * #ServiceRegistry(Iterator) constructor} of this
+   * <code>ServiceRegistry</code>.
+   *
+   * @see #getServiceProviders(Class, Filter, boolean)
+   */
+  public Iterator getServiceProviders(Class category, boolean useOrdering)
+  {
+    return getServiceProviders(category, null, useOrdering);
+  }
+
+
+  /**
+   * Retrieves all providers that have been registered for the
+   * specified service category and that satisfy the criteria
+   * of a custom filter.
+   *
+   * @param category the service category whose providers are
+   * to be retrieved.
+   *
+   * @param filter a custom filter, or <code>null</code> to
+   * retrieve all registered providers for the specified
+   * category.
+   *
+   * @param useOrdering <code>true</code> in order to retrieve the
+   * providers in an order imposed by the {@linkplain #setOrdering
+   * ordering constraints}; <code>false</code> in order to retrieve
+   * the providers in any order.
+   *
+   * @throws IllegalArgumentException if <code>category</code> is not
+   * among the categories passed to the {@linkplain
+   * #ServiceRegistry(Iterator) constructor} of this
+   * <code>ServiceRegistry</code>.
+   */
+  public synchronized Iterator getServiceProviders(Class category,
+                                                   Filter filter,
+                                                   boolean useOrdering)
+  {
+    int catid;
+    LinkedList provs;
+    ArrayList result;
+
+    catid = getCategoryID(category);
+    provs = providers[catid];
+    if (provs == null)
+      return Collections.EMPTY_LIST.iterator();
+    
+    result = new ArrayList(provs.size());
+    for (Iterator iter = provs.iterator(); iter.hasNext();)
+      {
+        Object provider = iter.next();
+        if (filter == null || filter.filter(provider))
+          result.add(provider);
+      }
+
+    // If we are supposed to obey ordering constraints, and
+    // if any constraints have been imposed on the specified
+    // service category, sort the result.
+    if (useOrdering && constraints != null)
+      {
+        final Map cons = constraints[catid];
+        if (cons != null)
+          Collections.sort(result, new Comparator()
+            {
+              public int compare(Object o1, Object o2)
+              {
+                Set s;
+
+                if (o1 == o2)
+                  return 0;
+                
+                s = (Set) cons.get(o1);
+                if (s != null && s.contains(o2))
+                  return -1;  // o1 < o2
+
+                s = (Set) cons.get(o2);
+                if (s != null && s.contains(o1))
+                  return 1;  // o1 > o2
+
+                return 0; // o1 == o2
+              }
+            });
+      }
+
+    return result.iterator();
+  }
+
+
+  /**
+   * Returns one of the service providers that is a subclass of the
+   * specified class.
+   * 
+   * @param providerClass a class to search for.
+   */
+  public synchronized Object getServiceProviderByClass(Class providerClass)
+  {
+    if (providerClass == null)
+      throw new IllegalArgumentException();
+
+    // Note that the method getServiceProviderByClass is rather
+    // unlikely to be ever called, so it would be wasteful to keep a
+    // special data structure for making it a fast operation.
+    for (int cat = 0; cat < categories.length; cat++)
+      {
+        if (!categories[cat].isAssignableFrom(providerClass))
+          continue;
+        
+        LinkedList provs = providers[cat];
+        if (provs == null)
+          continue;
+
+        for (Iterator iter = provs.iterator(); iter.hasNext();)
+          {
+            Object provider = iter.next();
+            if (providerClass.isInstance(provider))
+              return provider;
+          }
+      }
+
+    return null;
+  }
+
+
+  /**
+   * Adds an ordering constraint on service providers.
+   *
+   * @param category the service category to which an ordering
+   * constraint is to be added.
+   *
+   * @param first the provider which is supposed to come before
+   * <code>second</code>.
+   *
+   * @param second the provider which is supposed to come after
+   * <code>first</code>.
+   *
+   * @throws IllegalArgumentException if <code>first</code> and
+   * <code>second</code> are referring to the same object, or if one
+   * of them is <code>null</code>.
+   *
+   * @see #unsetOrdering
+   * @see #getServiceProviders(Class, Filter, boolean)
+   */
+  public synchronized boolean setOrdering(Class category,
+                                          Object firstProvider,
+                                          Object secondProvider)
+  {
+    return addConstraint(getCategoryID(category), firstProvider,
+                         secondProvider);
+  }
+
+
+  /**
+   * Removes an ordering constraint on service providers.
+   *
+   * @param category the service category from which an ordering
+   * constraint is to be removed.
+   *
+   * @param first the provider which is supposed to come before
+   * <code>second</code>.
+   *
+   * @param second the provider which is supposed to come after
+   * <code>first</code>.
+   *
+   * @throws IllegalArgumentException if <code>first</code> and
+   * <code>second</code> are referring to the same object, or if one
+   * of them is <code>null</code>.
+   *
+   * @see #setOrdering
+   */
+  public synchronized boolean unsetOrdering(Class category,
+                                            Object firstProvider,
+                                            Object secondProvider)
+  {
+    return removeConstraint(getCategoryID(category),
+                            firstProvider, secondProvider);
+  }
+
+
+  /**
+   * Adds an ordering constraint on service providers.
+   *
+   * @param catid the service category ID, which is the
+   * category&#x2019;s index into the {@link #categories} array.
+   *
+   * @param first the provider which is supposed to come before
+   * <code>second</code>.
+   *
+   * @param second the provider which is supposed to come after
+   * <code>first</code>.
+   *
+   * @throws IllegalArgumentException if <code>first</code> and
+   * <code>second</code> are referring to the same object, or if one
+   * of them is <code>null</code>.
+   */
+  private boolean addConstraint(int catid, Object first, Object second)
+  {
+    Set s;
+    IdentityHashMap cons;
+
+    // Also checks argument validity.
+    removeConstraint(catid, second, first);
+
+    if (constraints == null)
+      constraints = new IdentityHashMap[categories.length];
+    cons = constraints[catid];
+    if (cons == null)
+      cons = constraints[catid] = new IdentityHashMap();
+
+    s = (Set) cons.get(first);
+    if (s == null)
+      cons.put(first, s = new HashSet());
+    return s.add(second);
+  }
+
+
+  /**
+   * Removes an ordering constraint on service providers.
+   *
+   * @param catid the service category ID, which is the
+   * category&#x2019;s index into the {@link #categories} array.
+   *
+   * @param first the provider which is supposed to come before
+   * <code>second</code>.
+   *
+   * @param second the provider which is supposed to come after
+   * <code>first</code>.
+   *
+   * @throws IllegalArgumentException if <code>first</code> and
+   * <code>second</code> are referring to the same object, or if one
+   * of them is <code>null</code>.
+   */
+  private boolean removeConstraint(int catid, Object first, Object second)
+  {
+    Collection s;
+    IdentityHashMap cons;
+
+    if (first == null || second == null || first == second)
+      throw new IllegalArgumentException();
+
+    if (constraints == null)
+      return false;
+
+    cons = constraints[catid];
+    if (cons == null)
+      return false;
+
+    s = (Collection) cons.get(first);
+    if (s == null)
+      return false;
+
+    if (!s.remove(second))
+      return false;
+
+    // If we removed the last constraint for a service category,
+    // we can get free some memory.
+    if (cons.isEmpty())
+      {
+        constraints[catid] = null;
+        boolean anyConstraints = false;
+        for (int i = 0; i < constraints.length; i++)
+          {
+            if (constraints[i] != null)
+              {
+                anyConstraints = true;
+                break;
+              }
+          }
+        if (!anyConstraints)
+          constraints = null;
+      }
+
+    return true;
+  }
+
+
+  /**
+   * A filter for selecting service providers that match custom
+   * criteria.
+   *
+   * @see ServiceRegistry#getServiceProviders(Class, Filter,
+   * boolean)
+   *
+   * @since 1.4
+   *
+   * @author <a href="mailto:konqueror@gmx.de">Michael Koch</a>
+   * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+   */
+  public static interface Filter
+  {
+    /**
+     * Checks whether the specified service provider matches the
+     * constraints of this Filter.
+     *
+     * @param provider the service provider in question.
+     *
+     * @return <code>true</code> if <code>provider</code> matches the
+     * criteria; <code>false</code> if it does not match.
+     */
+    boolean filter(Object provider);
+  };
+}
+
diff --git a/libjava/javax/imageio/spi/package.html b/libjava/javax/imageio/spi/package.html
new file mode 100644 (file)
index 0000000..5c0779e
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in javax.imageio.spi package.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - javax.imageio.spi</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/javax/imageio/stream/IIOByteBuffer.java b/libjava/javax/imageio/stream/IIOByteBuffer.java
new file mode 100644 (file)
index 0000000..c9e230f
--- /dev/null
@@ -0,0 +1,94 @@
+/* IIOByteBuffer.java
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio.stream;
+
+/**
+ * A data structure for holding a reference to a byte array, an index
+ * into that array, and a number of bytes, that can be passed to one
+ * specific variant of the {@link
+ * javax.imageio.stream.ImageInputStream#readBytes(IIOByteBuffer, int)
+ * readBytes} method.
+ *
+ * @since 1.4
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public class IIOByteBuffer
+{
+  private byte[] data;
+  private int offset;
+  private int length;
+
+  public IIOByteBuffer(byte[] data, int offset, int length)
+  {
+    this.data = data;
+    this.offset = offset;
+    this.length = length;
+  }
+
+  public byte[] getData()
+  {
+    return data;
+  }
+
+  public void setData(byte[] data)
+  {
+    this.data = data;
+  }
+
+  public int getOffset()
+  {
+    return offset;
+  }
+
+  public void setOffset(int offset)
+  {
+    this.offset = offset;
+  }
+
+  public int getLength()
+  {
+    return length;
+  }
+
+  public void setLength(int length)
+  {
+    this.length = length;
+  }
+}
diff --git a/libjava/javax/imageio/stream/ImageInputStream.java b/libjava/javax/imageio/stream/ImageInputStream.java
new file mode 100644 (file)
index 0000000..4b509f8
--- /dev/null
@@ -0,0 +1,652 @@
+/* ImageInputStream.java
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio.stream;
+
+import java.io.DataInput;
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.ByteOrder;
+
+
+/**
+ * An input stream for use by {@link javax.imageio.ImageReader
+ * ImageReaders}.
+ *
+ * @since 1.4
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public interface ImageInputStream
+  extends DataInput
+{
+  void setByteOrder(ByteOrder order);
+
+  ByteOrder getByteOrder();
+  
+  int read()
+    throws IOException;
+
+  int read(byte[] b)
+    throws IOException;
+
+  int read(byte[] b, int offset, int length)
+    throws IOException;
+
+
+  /**
+   * Reads up to a specified number of bytes, and modifies a
+   * {@link IIOByteBuffer} to hold the read data.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   *
+   * @param buf an <code>IIOByteBuffer</code> that will hold the read
+   * data.
+   *
+   * @param numBytes the maximum number of bytes to read.
+   *
+   * @throws IndexOutOfBoundsException if <code>numBytes</code> is
+   * negative.
+   *
+   * @throws NullPointerException if <code>buf</code> is
+   * <code>null</code>.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   */
+  void readBytes(IIOByteBuffer buf, int numBytes)
+    throws IOException;
+
+
+  /**
+   * Reads a byte and checks whether or not its value is zero.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before the byte is read.
+   *
+   * @throws EOFException if the input stream is at its end.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readBit()
+   * @see #readByte()
+   * @see #readFully(byte[], int, int)
+   */
+  boolean readBoolean()
+    throws IOException;
+
+
+  /**
+   * Reads a signed byte.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   *
+   * @throws EOFException if the input stream is at its end.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readUnsignedByte()
+   * @see #readFully(byte[], int, int)
+   */
+  byte readByte()
+    throws IOException;
+
+
+  /**
+   * Reads an unsigned byte.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   *
+   * @throws EOFException if the input stream is at its end.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readByte()
+   * @see #readFully(byte[], int, int)
+   */
+  int readUnsignedByte()
+    throws IOException;
+
+
+  /**
+   * Reads an signed 16-bit integer. If necessary, the value gets
+   * converted from the stream&#x2019;s {@linkplain #getByteOrder()
+   * current byte order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @throws EOFException if the input stream ends before all two
+   * bytes were read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readUnsignedShort()
+   * @see #readChar()
+   * @see #readFully(short[], int, int)
+   */
+  short readShort()
+    throws IOException;
+
+
+  /**
+   * Reads an unsigned 16-bit integer. If necessary, the value gets
+   * converted from the stream&#x2019;s {@linkplain #getByteOrder()
+   * current byte order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * <p>This method does the same as {@link #readChar()}.
+   *
+   * @throws EOFException if the input stream ends before all two
+   * bytes were read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readShort()
+   * @see #readChar()
+   * @see #readFully(char[], int, int)
+   */
+  int readUnsignedShort()
+    throws IOException;
+
+
+  /**
+   * Reads an unsigned 16-bit integer. If necessary, the value gets
+   * converted from the stream&#x2019;s {@linkplain #getByteOrder()
+   * current byte order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * <p>This method does the same as {@link #readUnsignedShort()}.
+   *
+   * @throws EOFException if the input stream ends before all two
+   * bytes were read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readFully(char[], int, int)
+   */
+  char readChar()
+    throws IOException;
+
+
+  /**
+   * Reads a signed 32-bit integer. If necessary, the value gets
+   * converted from the stream&#x2019;s {@linkplain #getByteOrder()
+   * current byte order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @throws EOFException if the input stream ends before all four
+   * bytes were read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readUnsignedInt()
+   * @see #readFully(int[], int, int)
+   */
+  int readInt()
+    throws IOException;
+
+
+  /**
+   * Reads an unsigned 32-bit integer. If necessary, the value gets
+   * converted from the stream&#x2019;s {@linkplain #getByteOrder()
+   * current byte order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @throws EOFException if the input stream ends before all four
+   * bytes were read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readInt()
+   * @see #readFully(int[], int, int)
+   */
+  long readUnsignedInt()
+    throws IOException;
+
+
+  /**
+   * Reads a signed 64-bit integer. If necessary, the value gets
+   * converted from the stream&#x2019;s {@linkplain #getByteOrder()
+   * current byte order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @throws EOFException if the input stream ends before all eight
+   * bytes were read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readFully(long[], int, int)
+   */
+  long readLong()
+    throws IOException;
+
+
+  /**
+   * Reads an IEEE 32-bit single-precision floating point number. If
+   * necessary, the value gets converted from the stream&#x2019;s
+   * {@linkplain #getByteOrder() current byte order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @throws EOFException if the input stream ends before all four
+   * bytes were read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readFully(float[], int, int)
+   */
+  float readFloat()
+    throws IOException;
+
+
+  /**
+   * Reads an IEEE 64-bit double-precision floating point number. If
+   * necessary, the value gets converted from the stream&#x2019;s
+   * {@linkplain #getByteOrder() current byte order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @throws EOFException if the input stream ends before all eight
+   * bytes were read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readFully(double[], int, int)
+   */
+  double readDouble()
+    throws IOException;
+
+  String readLine()
+    throws IOException;
+
+  String readUTF()
+    throws IOException;
+
+
+  /**
+   * Reads a sequence of signed 8-bit integers into a
+   * <code>byte[]</code> array.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @param b an array for storing the read values.
+   *
+   * @param offset the index of the first element in <code>b</code>
+   * that will hold read data.
+   *
+   * @param numBytes the number of bytes to read.
+   *
+   * @throws IndexOutOfBoundsException if <code>offset</code> or
+   * <code>numBytes</code> is negative, or if <code>offset +
+   * numBytes</code> exceeds <code>b.length</code>.
+   *
+   * @throws NullPointerException if <code>b</code> is
+   * <code>null</code>.
+   *
+   * @throws EOFException if the input stream ends before all content
+   * was read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readByte()
+   */
+  void readFully(byte[] b, int offset, int numBytes)
+    throws IOException;
+
+
+  /**
+   * Reads a sequence of signed 8-bit integers into a
+   * <code>byte[]</code> array.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @param b an array for storing the read values.
+   *
+   * @throws NullPointerException if <code>b</code> is
+   * <code>null</code>.
+   *
+   * @throws EOFException if the input stream ends before all content
+   * was read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readByte()
+   * @see #readFully(byte[], int, int)
+   */
+  void readFully(byte[] b)
+    throws IOException;
+
+
+  /**
+   * Reads a sequence of signed 16-bit integers into a
+   * <code>short[]</code> array.  If necessary, values are converted
+   * from the stream&#x2019;s {@linkplain #getByteOrder() current byte
+   * order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @param s an array for storing the read values.
+   *
+   * @param offset the index of the first element in <code>s</code>
+   * that will hold read data.
+   *
+   * @param numShorts the number of signed 16-bit integers to read
+   * (which is one half of the number of bytes).
+   *
+   * @throws IndexOutOfBoundsException if <code>offset</code> or
+   * <code>numShorts</code> is negative, or if <code>offset +
+   * numShorts</code> exceeds <code>s.length</code>.
+   *
+   * @throws NullPointerException if <code>s</code> is
+   * <code>null</code>.
+   *
+   * @throws EOFException if the input stream ends before all content
+   * was read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readShort()
+   */
+  void readFully(short[] s, int offset, int numShorts)
+    throws IOException;
+
+
+  /**
+   * Reads a sequence of unsigned 16-bit integers into a
+   * <code>char[]</code> array.  If necessary, values are converted
+   * from the stream&#x2019;s {@linkplain #getByteOrder() current byte
+   * order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @param c an array for storing the read values.
+   *
+   * @param offset the index of the first element in <code>c</code>
+   * that will hold read data.
+   *
+   * @param numChars the number of unsigned 16-bit integers to read
+   * (which is one half of the number of bytes).
+   *
+   * @throws IndexOutOfBoundsException if <code>offset</code> or
+   * <code>numChars</code> is negative, or if <code>offset +
+   * numChars</code> exceeds <code>c.length</code>.
+   *
+   * @throws NullPointerException if <code>c</code> is
+   * <code>null</code>.
+   *
+   * @throws EOFException if the input stream ends before all content
+   * was read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readChar()
+   */
+  void readFully(char[] c, int offset, int numChars)
+    throws IOException;
+
+
+  /**
+   * Reads a sequence of signed 32-bit integers into a
+   * <code>long[]</code> array.  If necessary, values are converted
+   * from the stream&#x2019;s {@linkplain #getByteOrder() current byte
+   * order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @param i an array for storing the read values.
+   *
+   * @param offset the index of the first element in <code>i</code>
+   * that will hold read data.
+   *
+   * @param numLongs the number of signed 32-bit integers to read
+   * (which is one fourth of the number of bytes).
+   *
+   * @throws IndexOutOfBoundsException if <code>offset</code> or
+   * <code>numInts</code> is negative, or if <code>offset +
+   * numInts</code> exceeds <code>i.length</code>.
+   *
+   * @throws NullPointerException if <code>i</code> is
+   * <code>null</code>.
+   *
+   * @throws EOFException if the input stream ends before all content
+   * was read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readInt()
+   */
+  void readFully(int[] i, int offset, int numInts)
+    throws IOException;
+
+
+  /**
+   * Reads a sequence of signed 64-bit integers into a
+   * <code>long[]</code> array.  If necessary, values are converted
+   * from the stream&#x2019;s {@linkplain #getByteOrder() current byte
+   * order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @param l an array for storing the read values.
+   *
+   * @param offset the index of the first element in <code>l</code>
+   * that will hold read data.
+   *
+   * @param numLongs the number of signed 64-bit integers to read
+   * (which is one eight of the number of bytes).
+   *
+   * @throws IndexOutOfBoundsException if <code>offset</code> or
+   * <code>numLongs</code> is negative, or if <code>offset +
+   * numLongs</code> exceeds <code>l.length</code>.
+   *
+   * @throws NullPointerException if <code>l</code> is
+   * <code>null</code>.
+   *
+   * @throws EOFException if the input stream ends before all content
+   * was read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readLong()
+   */
+  void readFully(long[] l, int offset, int numLongs)
+    throws IOException;
+
+
+  /**
+   * Reads a sequence of IEEE 32-bit single-precision floating point
+   * numbers into a <code>float[]</code> array.  If necessary, values
+   * are converted from the stream&#x2019;s {@linkplain
+   * #getByteOrder() current byte order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @param d an array for storing the read values.
+   *
+   * @param offset the index of the first element in <code>d</code>
+   * that will hold read data.
+   *
+   * @param numFloats the number of IEEE 32-bit single-precision
+   * floating point numbers to read (which is one fourth of the number
+   * of bytes).
+   *
+   * @throws IndexOutOfBoundsException if <code>offset</code> or
+   * <code>numFloats</code> is negative, or if <code>offset +
+   * numFloats</code> exceeds <code>f.length</code>.
+   *
+   * @throws NullPointerException if <code>f</code> is
+   * <code>null</code>.
+   *
+   * @throws EOFException if the input stream ends before all content
+   * was read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readFloat()
+   */
+  void readFully(float[] f, int offset, int numFloats)
+    throws IOException;
+
+
+  /**
+   * Reads a sequence of IEEE 64-bit double-precision floating point
+   * numbers into a <code>double[]</code> array.  If necessary, values
+   * are converted from the stream&#x2019;s {@linkplain
+   * #getByteOrder() current byte order}.
+   *
+   * <p>The {@linkplain #getBitOffset() bit offset} is set to zero
+   * before any data is read.
+   * 
+   * @param d an array for storing the read values.
+   *
+   * @param offset the index of the first element in <code>d</code>
+   * that will hold read data.
+   *
+   * @param numDoubles the number of IEEE 64-bit double-precision
+   * floating point numbers to read (which is one eight of the number
+   * of bytes).
+   *
+   * @throws IndexOutOfBoundsException if <code>offset</code> or
+   * <code>numDoubles</code> is negative, or if <code>offset +
+   * numDoubles</code> exceeds <code>d.length</code>.
+   *
+   * @throws NullPointerException if <code>d</code> is
+   * <code>null</code>.
+   *
+   * @throws EOFException if the input stream ends before all content
+   * was read.
+   *
+   * @throws IOException if some general problem happens with
+   * accessing data.
+   *
+   * @see #readDouble()
+   */
+  void readFully(double[] d, int offset, int numDoubles)
+    throws IOException;
+
+  long getStreamPosition()
+    throws IOException;
+
+  int getBitOffset()
+    throws IOException;
+
+  void setBitOffset(int bitOffset)
+    throws IOException;
+
+  int readBit()
+    throws IOException;
+
+  long readBits(int numBits)
+    throws IOException;
+
+  long length()
+    throws IOException;
+
+  int skipBytes(int numBytes)
+    throws IOException;
+
+  long skipBytes(long numBytes)
+    throws IOException;
+
+  void seek(long pos)
+    throws IOException;
+
+  void mark()
+    throws IOException;
+
+  void reset()
+    throws IOException;
+
+  void flushBefore(long pos)
+    throws IOException;
+
+  void flush()
+    throws IOException;
+
+  long getFlushedPosition();
+
+  boolean isCached();
+
+  boolean isCachedMemory();
+
+  boolean isCachedFile();
+
+  void close()
+    throws IOException;
+}
diff --git a/libjava/javax/imageio/stream/ImageOutputStream.java b/libjava/javax/imageio/stream/ImageOutputStream.java
new file mode 100644 (file)
index 0000000..58a6594
--- /dev/null
@@ -0,0 +1,58 @@
+/* ImageOutputStream.java
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.imageio.stream;
+
+import java.io.DataOutput;
+
+
+/**
+ * An output stream for use by {@link javax.imageio.ImageWriter
+ * ImageWriters}.
+ *
+ * @since 1.4
+ *
+ * @author <a href="mailto:brawer@dandelis.ch">Sascha Brawer</a>
+ */
+public interface ImageOutputStream
+  extends ImageInputStream, DataOutput
+{
+  // FIXME: Incomplete. This interface is merely present in order to
+  // allow compilation of the javax.imageio.spi package, for which GNU
+  // Classpath does provide an implementation.
+}
diff --git a/libjava/javax/imageio/stream/package.html b/libjava/javax/imageio/stream/package.html
new file mode 100644 (file)
index 0000000..5449c12
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in javax.imageio.stream package.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - javax.imageio.stream</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>