jpl.mipl.util
Class SpiReader

java.lang.Object
  extended byjpl.mipl.util.SpiReader

public class SpiReader
extends Object

This class assists in reading a Service Provider Interface (SPI) file for use in auto-registration of services. This duplicates some functionality in both IIO and JAI 1.1, but since those classes are not public, we have to roll our own. All functions are static; the class cannot be instantiated.

An SPI file lives in the META-INF/services directory of a jar file (or in an exposed classpath directory). It typically lists class names that exist in that jar/directory that should be globally registered via some mechanism. For example, MICA uses this to register its Tools. IIO uses it to register file format plugins. JAI 1.1 uses it to register operators and codecs.

The nice thing about this mechanism is that the user merely has to dump a jar file containing the registration file into some place in the CLASSPATH, and it will be automatically found and dealt with.

This class provides assistance for finding and reading the SPI files; actually doing something with the lines in the SPI file is up to the caller. Comments (initial #) will be stripped, blank lines skipped, and leading/trailing blanks on the line will be eliminated.

The caller should find SPI files via the following mechanism:

     ClassLoader loader = this.getClass().getClassLoader();  // see below
     Enumeration enum = loader.getResources(
                        "META-INF/services/jpl.mipl.mica.MicaToolsSpi");
     while (enum.hasMoreElements()) {
         Collection lines = SpiReader.readSpi((URL)enum.nextElement());
         Iterator it = lines.iterator();
         while (it.hasNext()) {
             String l = (String)it.next();
             ... process this line ...
         }
     }
 
Note the two loops. The outer loops over each SPI file (e.g. each jar file), while the inner loops over each line in the file. A Collection of Strings is returned after comments, blank lines, and leading/trailing blanks have been stripped.

The SPI filename should start with "META-INF/services/" and the filename part should include the fully-qualified package name of the entity doing the registration (MICA, in this case). This will prevent name collisions.

The ClassLoader is usually the system default loader; this will cause $CLASSPATH to be searched. If you want to load a plugin at runtime, you need a special class loader like URLClassLoader for the jar anyway; this is then what should be used to get the resources.

As a convenience, for users that do not need to keep track of different jar files, a single Collection of lines from all SPI files (concatenated together) may be obtained via SpiReader.readAllSpis(). Then the above example becomes:

     Collection lines = SpiReader.readAllSpis(
                     "META-INF/services/jpl.mipl.mica.MicaToolsSpi", null);
     Iterator it = lines.iterator();
     while (it.hasNext()) {
         String l = (String)it.next();
         ... process this line ...
     }
 


Constructor Summary
SpiReader()
           
 
Method Summary
static String getContainerName(URL url)
          Attempts to determine the "name" of the entity containing the SPI, given the URL.
static String getContainerPathname(URL url)
          Attempts to determine the pathname of the entity containing the SPI, given the URL.
static Collection readAllSpis(String name, ClassLoader loader)
          Convenience routine to read in all SPI's at once.
static Collection readSpi(URL url)
          Reads a file and returns a Collection of valid lines.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

SpiReader

public SpiReader()
Method Detail

readSpi

public static Collection readSpi(URL url)
                          throws IOException
Reads a file and returns a Collection of valid lines. The following are stripped out: There is actually nothing specific to SPI's about this function; it could be used for reading any kind of configuration or similar file.

Throws:
IOException - if the URL being read does

readAllSpis

public static Collection readAllSpis(String name,
                                     ClassLoader loader)
                              throws IOException
Convenience routine to read in all SPI's at once. Use this if you don't care which entries came from which jar file.

Parameters:
name - The name of the file, should start with META-INF/services/. See class comments.
loader - The class loader to use. If null, the system class loader is used.
Returns:
A single Collection containing all the lines from the files, as massaged by readSpi().
Throws:
IOException - if any called routines do.

getContainerPathname

public static String getContainerPathname(URL url)
Attempts to determine the pathname of the entity containing the SPI, given the URL. If the entity is a jar file, the pathname of the jar (with path and extensions) is returned. If it is a file, the last directory element before META-INF is returned. If the name cannot be determined, null is returned.

See Also:
JarURLConnection, getContainerName(java.net.URL)

getContainerName

public static String getContainerName(URL url)
Attempts to determine the "name" of the entity containing the SPI, given the URL. If the entity is a jar file, the simple name of the jar (without path or extensions) is returned. If it is a file, the last directory element before META-INF is returned. If the name cannot be determined, null is returned.

See Also:
JarURLConnection, getContainerPathname(java.net.URL)