1 /*
   2  * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.imageio.spi;
  27 
  28 import java.io.IOException;
  29 import javax.imageio.ImageReader;
  30 import javax.imageio.stream.ImageInputStream;
  31 
  32 /**
  33  * The service provider interface (SPI) for <code>ImageReader</code>s.
  34  * For more information on service provider classes, see the class comment
  35  * for the <code>IIORegistry</code> class.
  36  *
  37  * <p> Each <code>ImageReaderSpi</code> provides several types of information
  38  * about the <code>ImageReader</code> class with which it is associated.
  39  *
  40  * <p> The name of the vendor who defined the SPI class and a
  41  * brief description of the class are available via the
  42  * <code>getVendorName</code>, <code>getDescription</code>,
  43  * and <code>getVersion</code> methods.
  44  * These methods may be internationalized to provide locale-specific
  45  * output.  These methods are intended mainly to provide short,
  46  * human-readable information that might be used to organize a pop-up
  47  * menu or other list.
  48  *
  49  * <p> Lists of format names, file suffixes, and MIME types associated
  50  * with the service may be obtained by means of the
  51  * <code>getFormatNames</code>, <code>getFileSuffixes</code>, and
  52  * <code>getMIMETypes</code> methods.  These methods may be used to
  53  * identify candidate <code>ImageReader</code>s for decoding a
  54  * particular file or stream based on manual format selection, file
  55  * naming, or MIME associations (for example, when accessing a file
  56  * over HTTP or as an email attachment).
  57  *
  58  * <p> A more reliable way to determine which <code>ImageReader</code>s
  59  * are likely to be able to parse a particular data stream is provided
  60  * by the <code>canDecodeInput</code> method.  This methods allows the
  61  * service provider to inspect the actual stream contents.
  62  *
  63  * <p> Finally, an instance of the <code>ImageReader</code> class
  64  * associated with this service provider may be obtained by calling
  65  * the <code>createReaderInstance</code> method.  Any heavyweight
  66  * initialization, such as the loading of native libraries or creation
  67  * of large tables, should be deferred at least until the first
  68  * invocation of this method.
  69  *
  70  * @see IIORegistry
  71  * @see javax.imageio.ImageReader
  72  *
  73  */
  74 public abstract class ImageReaderSpi extends ImageReaderWriterSpi {
  75 
  76     /**
  77      * A single-element array, initially containing
  78      * <code>ImageInputStream.class</code>, to be returned from
  79      * <code>getInputTypes</code>.
  80      * @deprecated Instead of using this field, directly create
  81      * the equivalent array <code>{ ImageInputStream.class }</code>.
  82      */
  83     @Deprecated
  84     public static final Class[] STANDARD_INPUT_TYPE =
  85         { ImageInputStream.class };
  86 
  87     /**
  88      * An array of <code>Class</code> objects to be returned from
  89      * <code>getInputTypes</code>, initially <code>null</code>.
  90      */
  91     protected Class[] inputTypes = null;
  92 
  93     /**
  94      * An array of strings to be returned from
  95      * <code>getImageWriterSpiNames</code>, initially
  96      * <code>null</code>.
  97      */
  98     protected String[] writerSpiNames = null;
  99 
 100     /**
 101      * The <code>Class</code> of the reader, initially
 102      * <code>null</code>.
 103      */
 104     private Class readerClass = null;
 105 
 106     /**
 107      * Constructs a blank <code>ImageReaderSpi</code>.  It is up to
 108      * the subclass to initialize instance variables and/or override
 109      * method implementations in order to provide working versions of
 110      * all methods.
 111      */
 112     protected ImageReaderSpi() {
 113     }
 114 
 115     /**
 116      * Constructs an <code>ImageReaderSpi</code> with a given
 117      * set of values.
 118      *
 119      * @param vendorName the vendor name, as a non-<code>null</code>
 120      * <code>String</code>.
 121      * @param version a version identifier, as a non-<code>null</code>
 122      * <code>String</code>.
 123      * @param names a non-<code>null</code> array of
 124      * <code>String</code>s indicating the format names.  At least one
 125      * entry must be present.
 126      * @param suffixes an array of <code>String</code>s indicating the
 127      * common file suffixes.  If no suffixes are defined,
 128      * <code>null</code> should be supplied.  An array of length 0
 129      * will be normalized to <code>null</code>.
 130      * @param MIMETypes an array of <code>String</code>s indicating
 131      * the format's MIME types.  If no MIME types are defined,
 132      * <code>null</code> should be supplied.  An array of length 0
 133      * will be normalized to <code>null</code>.
 134      * @param readerClassName the fully-qualified name of the
 135      * associated <code>ImageReader</code> class, as a
 136      * non-<code>null</code> <code>String</code>.
 137      * @param inputTypes a non-<code>null</code> array of
 138      * <code>Class</code> objects of length at least 1 indicating the
 139      * legal input types.
 140      * @param writerSpiNames an array <code>String</code>s naming the
 141      * classes of all associated <code>ImageWriter</code>s, or
 142      * <code>null</code>.  An array of length 0 is normalized to
 143      * <code>null</code>.
 144      * @param supportsStandardStreamMetadataFormat a
 145      * <code>boolean</code> that indicates whether a stream metadata
 146      * object can use trees described by the standard metadata format.
 147      * @param nativeStreamMetadataFormatName a
 148      * <code>String</code>, or <code>null</code>, to be returned from
 149      * <code>getNativeStreamMetadataFormatName</code>.
 150      * @param nativeStreamMetadataFormatClassName a
 151      * <code>String</code>, or <code>null</code>, to be used to instantiate
 152      * a metadata format object to be returned from
 153      * <code>getNativeStreamMetadataFormat</code>.
 154      * @param extraStreamMetadataFormatNames an array of
 155      * <code>String</code>s, or <code>null</code>, to be returned from
 156      * <code>getExtraStreamMetadataFormatNames</code>.  An array of length
 157      * 0 is normalized to <code>null</code>.
 158      * @param extraStreamMetadataFormatClassNames an array of
 159      * <code>String</code>s, or <code>null</code>, to be used to instantiate
 160      * a metadata format object to be returned from
 161      * <code>getStreamMetadataFormat</code>.  An array of length
 162      * 0 is normalized to <code>null</code>.
 163      * @param supportsStandardImageMetadataFormat a
 164      * <code>boolean</code> that indicates whether an image metadata
 165      * object can use trees described by the standard metadata format.
 166      * @param nativeImageMetadataFormatName a
 167      * <code>String</code>, or <code>null</code>, to be returned from
 168      * <code>getNativeImageMetadataFormatName</code>.
 169      * @param nativeImageMetadataFormatClassName a
 170      * <code>String</code>, or <code>null</code>, to be used to instantiate
 171      * a metadata format object to be returned from
 172      * <code>getNativeImageMetadataFormat</code>.
 173      * @param extraImageMetadataFormatNames an array of
 174      * <code>String</code>s to be returned from
 175      * <code>getExtraImageMetadataFormatNames</code>.  An array of length 0
 176      * is normalized to <code>null</code>.
 177      * @param extraImageMetadataFormatClassNames an array of
 178      * <code>String</code>s, or <code>null</code>, to be used to instantiate
 179      * a metadata format object to be returned from
 180      * <code>getImageMetadataFormat</code>.  An array of length
 181      * 0 is normalized to <code>null</code>.
 182      *
 183      * @exception IllegalArgumentException if <code>vendorName</code>
 184      * is <code>null</code>.
 185      * @exception IllegalArgumentException if <code>version</code>
 186      * is <code>null</code>.
 187      * @exception IllegalArgumentException if <code>names</code>
 188      * is <code>null</code> or has length 0.
 189      * @exception IllegalArgumentException if <code>readerClassName</code>
 190      * is <code>null</code>.
 191      * @exception IllegalArgumentException if <code>inputTypes</code>
 192      * is <code>null</code> or has length 0.
 193      */
 194     public ImageReaderSpi(String vendorName,
 195                           String version,
 196                           String[] names,
 197                           String[] suffixes,
 198                           String[] MIMETypes,
 199                           String readerClassName,
 200                           Class[] inputTypes,
 201                           String[] writerSpiNames,
 202                           boolean supportsStandardStreamMetadataFormat,
 203                           String nativeStreamMetadataFormatName,
 204                           String nativeStreamMetadataFormatClassName,
 205                           String[] extraStreamMetadataFormatNames,
 206                           String[] extraStreamMetadataFormatClassNames,
 207                           boolean supportsStandardImageMetadataFormat,
 208                           String nativeImageMetadataFormatName,
 209                           String nativeImageMetadataFormatClassName,
 210                           String[] extraImageMetadataFormatNames,
 211                           String[] extraImageMetadataFormatClassNames) {
 212         super(vendorName, version,
 213               names, suffixes, MIMETypes, readerClassName,
 214               supportsStandardStreamMetadataFormat,
 215               nativeStreamMetadataFormatName,
 216               nativeStreamMetadataFormatClassName,
 217               extraStreamMetadataFormatNames,
 218               extraStreamMetadataFormatClassNames,
 219               supportsStandardImageMetadataFormat,
 220               nativeImageMetadataFormatName,
 221               nativeImageMetadataFormatClassName,
 222               extraImageMetadataFormatNames,
 223               extraImageMetadataFormatClassNames);
 224 
 225         if (inputTypes == null) {
 226             throw new IllegalArgumentException
 227                 ("inputTypes == null!");
 228         }
 229         if (inputTypes.length == 0) {
 230             throw new IllegalArgumentException
 231                 ("inputTypes.length == 0!");
 232         }
 233 
 234         this.inputTypes = (inputTypes == STANDARD_INPUT_TYPE) ?
 235             new Class<?>[] { ImageInputStream.class } :
 236             inputTypes.clone();
 237 
 238         // If length == 0, leave it null
 239         if (writerSpiNames != null && writerSpiNames.length > 0) {
 240             this.writerSpiNames = writerSpiNames.clone();
 241         }
 242     }
 243 
 244     /**
 245      * Returns an array of <code>Class</code> objects indicating what
 246      * types of objects may be used as arguments to the reader's
 247      * <code>setInput</code> method.
 248      *
 249      * <p> For most readers, which only accept input from an
 250      * <code>ImageInputStream</code>, a single-element array
 251      * containing <code>ImageInputStream.class</code> should be
 252      * returned.
 253      *
 254      * @return a non-<code>null</code> array of
 255      * <code>Class</code>objects of length at least 1.
 256      */
 257     public Class[] getInputTypes() {
 258         return inputTypes.clone();
 259     }
 260 
 261     /**
 262      * Returns <code>true</code> if the supplied source object appears
 263      * to be of the format supported by this reader.  Returning
 264      * <code>true</code> from this method does not guarantee that
 265      * reading will succeed, only that there appears to be a
 266      * reasonable chance of success based on a brief inspection of the
 267      * stream contents.  If the source is an
 268      * <code>ImageInputStream</code>, implementations will commonly
 269      * check the first several bytes of the stream for a "magic
 270      * number" associated with the format.  Once actual reading has
 271      * commenced, the reader may still indicate failure at any time
 272      * prior to the completion of decoding.
 273      *
 274      * <p> It is important that the state of the object not be
 275      * disturbed in order that other <code>ImageReaderSpi</code>s can
 276      * properly determine whether they are able to decode the object.
 277      * In particular, if the source is an
 278      * <code>ImageInputStream</code>, a
 279      * <code>mark</code>/<code>reset</code> pair should be used to
 280      * preserve the stream position.
 281      *
 282      * <p> Formats such as "raw," which can potentially attempt
 283      * to read nearly any stream, should return <code>false</code>
 284      * in order to avoid being invoked in preference to a closer
 285      * match.
 286      *
 287      * <p> If <code>source</code> is not an instance of one of the
 288      * classes returned by <code>getInputTypes</code>, the method
 289      * should simply return <code>false</code>.
 290      *
 291      * @param source the object (typically an
 292      * <code>ImageInputStream</code>) to be decoded.
 293      *
 294      * @return <code>true</code> if it is likely that this stream can
 295      * be decoded.
 296      *
 297      * @exception IllegalArgumentException if <code>source</code> is
 298      * <code>null</code>.
 299      * @exception IOException if an I/O error occurs while reading the
 300      * stream.
 301      */
 302     public abstract boolean canDecodeInput(Object source) throws IOException;
 303 
 304     /**
 305      * Returns an instance of the <code>ImageReader</code>
 306      * implementation associated with this service provider.
 307      * The returned object will initially be in an initial state
 308      * as if its <code>reset</code> method had been called.
 309      *
 310      * <p> The default implementation simply returns
 311      * <code>createReaderInstance(null)</code>.
 312      *
 313      * @return an <code>ImageReader</code> instance.
 314      *
 315      * @exception IOException if an error occurs during loading,
 316      * or initialization of the reader class, or during instantiation
 317      * or initialization of the reader object.
 318      */
 319     public ImageReader createReaderInstance() throws IOException {
 320         return createReaderInstance(null);
 321     }
 322 
 323     /**
 324      * Returns an instance of the <code>ImageReader</code>
 325      * implementation associated with this service provider.
 326      * The returned object will initially be in an initial state
 327      * as if its <code>reset</code> method had been called.
 328      *
 329      * <p> An <code>Object</code> may be supplied to the plug-in at
 330      * construction time.  The nature of the object is entirely
 331      * plug-in specific.
 332      *
 333      * <p> Typically, a plug-in will implement this method using code
 334      * such as <code>return new MyImageReader(this)</code>.
 335      *
 336      * @param extension a plug-in specific extension object, which may
 337      * be <code>null</code>.
 338      *
 339      * @return an <code>ImageReader</code> instance.
 340      *
 341      * @exception IOException if the attempt to instantiate
 342      * the reader fails.
 343      * @exception IllegalArgumentException if the
 344      * <code>ImageReader</code>'s constructor throws an
 345      * <code>IllegalArgumentException</code> to indicate that the
 346      * extension object is unsuitable.
 347      */
 348     public abstract ImageReader createReaderInstance(Object extension)
 349         throws IOException;
 350 
 351     /**
 352      * Returns <code>true</code> if the <code>ImageReader</code> object
 353      * passed in is an instance of the <code>ImageReader</code>
 354      * associated with this service provider.
 355      *
 356      * <p> The default implementation compares the fully-qualified
 357      * class name of the <code>reader</code> argument with the class
 358      * name passed into the constructor.  This method may be overridden
 359      * if more sophisticated checking is required.
 360      *
 361      * @param reader an <code>ImageReader</code> instance.
 362      *
 363      * @return <code>true</code> if <code>reader</code> is recognized.
 364      *
 365      * @exception IllegalArgumentException if <code>reader</code> is
 366      * <code>null</code>.
 367      */
 368     public boolean isOwnReader(ImageReader reader) {
 369         if (reader == null) {
 370             throw new IllegalArgumentException("reader == null!");
 371         }
 372         String name = reader.getClass().getName();
 373         return name.equals(pluginClassName);
 374     }
 375 
 376     /**
 377      * Returns an array of <code>String</code>s containing the fully
 378      * qualified names of all the <code>ImageWriterSpi</code> classes
 379      * that can understand the internal metadata representation used
 380      * by the <code>ImageReader</code> associated with this service
 381      * provider, or <code>null</code> if there are no such
 382      * <code>ImageWriter</code>s specified.  If a
 383      * non-<code>null</code> value is returned, it must have non-zero
 384      * length.
 385      *
 386      * <p> The first item in the array must be the name of the service
 387      * provider for the "preferred" writer, as it will be used to
 388      * instantiate the <code>ImageWriter</code> returned by
 389      * <code>ImageIO.getImageWriter(ImageReader)</code>.
 390      *
 391      * <p> This mechanism may be used to obtain
 392      * <code>ImageWriters</code> that will understand the internal
 393      * structure of non-pixel meta-data (see
 394      * <code>IIOTreeInfo</code>) generated by an
 395      * <code>ImageReader</code>.  By obtaining this data from the
 396      * <code>ImageReader</code> and passing it on to one of the
 397      * <code>ImageWriters</code> obtained with this method, a client
 398      * program can read an image, modify it in some way, and write it
 399      * back out while preserving all meta-data, without having to
 400      * understand anything about the internal structure of the
 401      * meta-data, or even about the image format.
 402      *
 403      * @return an array of <code>String</code>s of length at least 1
 404      * containing names of <code>ImageWriterSpi</code>, or
 405      * <code>null</code>.
 406      *
 407      * @see javax.imageio.ImageIO#getImageWriter(ImageReader)
 408      */
 409     public String[] getImageWriterSpiNames() {
 410         return writerSpiNames == null ?
 411             null : writerSpiNames.clone();
 412     }
 413 }