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