001 /*
002 * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.imageio.spi;
027
028 import java.io.IOException;
029 import java.lang.reflect.Constructor;
030 import java.lang.reflect.Method;
031 import java.util.Arrays;
032 import java.util.Iterator;
033 import javax.imageio.ImageReader;
034 import javax.imageio.metadata.IIOMetadata;
035 import javax.imageio.metadata.IIOMetadataFormat;
036 import javax.imageio.metadata.IIOMetadataFormatImpl;
037 import javax.imageio.stream.ImageInputStream;
038
039 /**
040 * A superclass containing instance variables and methods common to
041 * <code>ImageReaderSpi</code> and <code>ImageWriterSpi</code>.
042 *
043 * @see IIORegistry
044 * @see ImageReaderSpi
045 * @see ImageWriterSpi
046 *
047 * @version 0.5
048 */
049 public abstract class ImageReaderWriterSpi extends IIOServiceProvider {
050
051 /**
052 * An array of strings to be returned from
053 * <code>getFormatNames</code>, initially <code>null</code>.
054 * Constructors should set this to a non-<code>null</code> value.
055 */
056 protected String[] names = null;
057
058 /**
059 * An array of strings to be returned from
060 * <code>getFileSuffixes</code>, initially <code>null</code>.
061 */
062 protected String[] suffixes = null;
063
064 /**
065 * An array of strings to be returned from
066 * <code>getMIMETypes</code>, initially <code>null</code>.
067 */
068 protected String[] MIMETypes = null;
069
070 /**
071 * A <code>String</code> containing the name of the associated
072 * plug-in class, initially <code>null</code>.
073 */
074 protected String pluginClassName = null;
075
076 /**
077 * A boolean indicating whether this plug-in supports the
078 * standard metadata format for stream metadata, initially
079 * <code>false</code>.
080 */
081 protected boolean supportsStandardStreamMetadataFormat = false;
082
083 /**
084 * A <code>String</code> containing the name of the native stream
085 * metadata format supported by this plug-in, initially
086 * <code>null</code>.
087 */
088 protected String nativeStreamMetadataFormatName = null;
089
090 /**
091 * A <code>String</code> containing the class name of the native
092 * stream metadata format supported by this plug-in, initially
093 * <code>null</code>.
094 */
095 protected String nativeStreamMetadataFormatClassName = null;
096
097 /**
098 * An array of <code>String</code>s containing the names of any
099 * additional stream metadata formats supported by this plug-in,
100 * initially <code>null</code>.
101 */
102 protected String[] extraStreamMetadataFormatNames = null;
103
104 /**
105 * An array of <code>String</code>s containing the class names of
106 * any additional stream metadata formats supported by this plug-in,
107 * initially <code>null</code>.
108 */
109 protected String[] extraStreamMetadataFormatClassNames = null;
110
111 /**
112 * A boolean indicating whether this plug-in supports the
113 * standard metadata format for image metadata, initially
114 * <code>false</code>.
115 */
116 protected boolean supportsStandardImageMetadataFormat = false;
117
118 /**
119 * A <code>String</code> containing the name of the
120 * native stream metadata format supported by this plug-in,
121 * initially <code>null</code>.
122 */
123 protected String nativeImageMetadataFormatName = null;
124
125 /**
126 * A <code>String</code> containing the class name of the
127 * native stream metadata format supported by this plug-in,
128 * initially <code>null</code>.
129 */
130 protected String nativeImageMetadataFormatClassName = null;
131
132 /**
133 * An array of <code>String</code>s containing the names of any
134 * additional image metadata formats supported by this plug-in,
135 * initially <code>null</code>.
136 */
137 protected String[] extraImageMetadataFormatNames = null;
138
139 /**
140 * An array of <code>String</code>s containing the class names of
141 * any additional image metadata formats supported by this
142 * plug-in, initially <code>null</code>.
143 */
144 protected String[] extraImageMetadataFormatClassNames = null;
145
146 /**
147 * Constructs an <code>ImageReaderWriterSpi</code> with a given
148 * set of values.
149 *
150 * @param vendorName the vendor name, as a non-<code>null</code>
151 * <code>String</code>.
152 * @param version a version identifier, as a non-<code>null</code>
153 * <code>String</code>.
154 * @param names a non-<code>null</code> array of
155 * <code>String</code>s indicating the format names. At least one
156 * entry must be present.
157 * @param suffixes an array of <code>String</code>s indicating the
158 * common file suffixes. If no suffixes are defined,
159 * <code>null</code> should be supplied. An array of length 0
160 * will be normalized to <code>null</code>.
161 * @param MIMETypes an array of <code>String</code>s indicating
162 * the format's MIME types. If no MIME types are defined,
163 * <code>null</code> should be supplied. An array of length 0
164 * will be normalized to <code>null</code>.
165 * @param pluginClassName the fully-qualified name of the
166 * associated <code>ImageReader</code> or <code>ImageWriter</code>
167 * class, as a non-<code>null</code> <code>String</code>.
168 * @param supportsStandardStreamMetadataFormat a
169 * <code>boolean</code> that indicates whether a stream metadata
170 * object can use trees described by the standard metadata format.
171 * @param nativeStreamMetadataFormatName a
172 * <code>String</code>, or <code>null</code>, to be returned from
173 * <code>getNativeStreamMetadataFormatName</code>.
174 * @param nativeStreamMetadataFormatClassName a
175 * <code>String</code>, or <code>null</code>, to be used to instantiate
176 * a metadata format object to be returned from
177 * <code>getNativeStreamMetadataFormat</code>.
178 * @param extraStreamMetadataFormatNames an array of
179 * <code>String</code>s, or <code>null</code>, to be returned from
180 * <code>getExtraStreamMetadataFormatNames</code>. An array of length
181 * 0 is normalized to <code>null</code>.
182 * @param extraStreamMetadataFormatClassNames an array of
183 * <code>String</code>s, or <code>null</code>, to be used to instantiate
184 * a metadata format object to be returned from
185 * <code>getStreamMetadataFormat</code>. An array of length
186 * 0 is normalized to <code>null</code>.
187 * @param supportsStandardImageMetadataFormat a
188 * <code>boolean</code> that indicates whether an image metadata
189 * object can use trees described by the standard metadata format.
190 * @param nativeImageMetadataFormatName a
191 * <code>String</code>, or <code>null</code>, to be returned from
192 * <code>getNativeImageMetadataFormatName</code>.
193 * @param nativeImageMetadataFormatClassName a
194 * <code>String</code>, or <code>null</code>, to be used to instantiate
195 * a metadata format object to be returned from
196 * <code>getNativeImageMetadataFormat</code>.
197 * @param extraImageMetadataFormatNames an array of
198 * <code>String</code>s to be returned from
199 * <code>getExtraImageMetadataFormatNames</code>. An array of length 0
200 * is normalized to <code>null</code>.
201 * @param extraImageMetadataFormatClassNames an array of
202 * <code>String</code>s, or <code>null</code>, to be used to instantiate
203 * a metadata format object to be returned from
204 * <code>getImageMetadataFormat</code>. An array of length
205 * 0 is normalized to <code>null</code>.
206 *
207 * @exception IllegalArgumentException if <code>vendorName</code>
208 * is <code>null</code>.
209 * @exception IllegalArgumentException if <code>version</code>
210 * is <code>null</code>.
211 * @exception IllegalArgumentException if <code>names</code>
212 * is <code>null</code> or has length 0.
213 * @exception IllegalArgumentException if <code>pluginClassName</code>
214 * is <code>null</code>.
215 */
216 public ImageReaderWriterSpi(String vendorName, String version,
217 String[] names, String[] suffixes, String[] MIMETypes,
218 String pluginClassName,
219 boolean supportsStandardStreamMetadataFormat,
220 String nativeStreamMetadataFormatName,
221 String nativeStreamMetadataFormatClassName,
222 String[] extraStreamMetadataFormatNames,
223 String[] extraStreamMetadataFormatClassNames,
224 boolean supportsStandardImageMetadataFormat,
225 String nativeImageMetadataFormatName,
226 String nativeImageMetadataFormatClassName,
227 String[] extraImageMetadataFormatNames,
228 String[] extraImageMetadataFormatClassNames) {
229 super (vendorName, version);
230 if (names == null) {
231 throw new IllegalArgumentException("names == null!");
232 }
233 if (names.length == 0) {
234 throw new IllegalArgumentException("names.length == 0!");
235 }
236 if (pluginClassName == null) {
237 throw new IllegalArgumentException(
238 "pluginClassName == null!");
239 }
240
241 this .names = (String[]) names.clone();
242 // If length == 0, leave it null
243 if (suffixes != null && suffixes.length > 0) {
244 this .suffixes = (String[]) suffixes.clone();
245 }
246 // If length == 0, leave it null
247 if (MIMETypes != null && MIMETypes.length > 0) {
248 this .MIMETypes = (String[]) MIMETypes.clone();
249 }
250 this .pluginClassName = pluginClassName;
251
252 this .supportsStandardStreamMetadataFormat = supportsStandardStreamMetadataFormat;
253 this .nativeStreamMetadataFormatName = nativeStreamMetadataFormatName;
254 this .nativeStreamMetadataFormatClassName = nativeStreamMetadataFormatClassName;
255 // If length == 0, leave it null
256 if (extraStreamMetadataFormatNames != null
257 && extraStreamMetadataFormatNames.length > 0) {
258 this .extraStreamMetadataFormatNames = (String[]) extraStreamMetadataFormatNames
259 .clone();
260 }
261 // If length == 0, leave it null
262 if (extraStreamMetadataFormatClassNames != null
263 && extraStreamMetadataFormatClassNames.length > 0) {
264 this .extraStreamMetadataFormatClassNames = (String[]) extraStreamMetadataFormatClassNames
265 .clone();
266 }
267 this .supportsStandardImageMetadataFormat = supportsStandardImageMetadataFormat;
268 this .nativeImageMetadataFormatName = nativeImageMetadataFormatName;
269 this .nativeImageMetadataFormatClassName = nativeImageMetadataFormatClassName;
270 // If length == 0, leave it null
271 if (extraImageMetadataFormatNames != null
272 && extraImageMetadataFormatNames.length > 0) {
273 this .extraImageMetadataFormatNames = (String[]) extraImageMetadataFormatNames
274 .clone();
275 }
276 // If length == 0, leave it null
277 if (extraImageMetadataFormatClassNames != null
278 && extraImageMetadataFormatClassNames.length > 0) {
279 this .extraImageMetadataFormatClassNames = (String[]) extraImageMetadataFormatClassNames
280 .clone();
281 }
282 }
283
284 /**
285 * Constructs a blank <code>ImageReaderWriterSpi</code>. It is up
286 * to the subclass to initialize instance variables and/or
287 * override method implementations in order to provide working
288 * versions of all methods.
289 */
290 public ImageReaderWriterSpi() {
291 }
292
293 /**
294 * Returns an array of <code>String</code>s containing
295 * human-readable names for the formats that are generally usable
296 * by the <code>ImageReader</code> or <code>ImageWriter</code>
297 * implementation associated with this service provider. For
298 * example, a single <code>ImageReader</code> might be able to
299 * process both PBM and PNM files.
300 *
301 * @return a non-<code>null</code> array of <code>String</code>s
302 * or length at least 1 containing informal format names
303 * associated with this reader or writer.
304 */
305 public String[] getFormatNames() {
306 return (String[]) names.clone();
307 }
308
309 /**
310 * Returns an array of <code>String</code>s containing a list of
311 * file suffixes associated with the formats that are generally
312 * usable by the <code>ImageReader</code> or
313 * <code>ImageWriter</code> implementation associated with this
314 * service provider. For example, a single
315 * <code>ImageReader</code> might be able to process files with
316 * '.pbm' and '.pnm' suffixes, or both '.jpg' and '.jpeg'
317 * suffixes. If there are no known file suffixes,
318 * <code>null</code> will be returned.
319 *
320 * <p> Returning a particular suffix does not guarantee that files
321 * with that suffix can be processed; it merely indicates that it
322 * may be worthwhile attempting to decode or encode such files
323 * using this service provider.
324 *
325 * @return an array of <code>String</code>s or length at least 1
326 * containing common file suffixes associated with this reader or
327 * writer, or <code>null</code>.
328 */
329 public String[] getFileSuffixes() {
330 return suffixes == null ? null : (String[]) suffixes.clone();
331 }
332
333 /**
334 * Returns an array of <code>String</code>s containing a list of
335 * MIME types associated with the formats that are generally
336 * usable by the <code>ImageReader</code> or
337 * <code>ImageWriter</code> implementation associated with this
338 * service provider.
339 *
340 * <p> Ideally, only a single MIME type would be required in order
341 * to describe a particular format. However, for several reasons
342 * it is necessary to associate a list of types with each service
343 * provider. First, many common image file formats do not have
344 * standard MIME types, so a list of commonly used unofficial
345 * names will be required, such as <code>image/x-pbm</code> and
346 * <code>image/x-portable-bitmap</code>. Some file formats have
347 * official MIME types but may sometimes be referred to using
348 * their previous unofficial designations, such as
349 * <code>image/x-png</code> instead of the official
350 * <code>image/png</code>. Finally, a single service provider may
351 * be capable of parsing multiple distinct types from the MIME
352 * point of view, for example <code>image/x-xbitmap</code> and
353 * <code>image/x-xpixmap</code>.
354 *
355 * <p> Returning a particular MIME type does not guarantee that
356 * files claiming to be of that type can be processed; it merely
357 * indicates that it may be worthwhile attempting to decode or
358 * encode such files using this service provider.
359 *
360 * @return an array of <code>String</code>s or length at least 1
361 * containing MIME types associated with this reader or writer, or
362 * <code>null</code>.
363 */
364 public String[] getMIMETypes() {
365 return MIMETypes == null ? null : (String[]) MIMETypes.clone();
366 }
367
368 /**
369 * Returns the fully-qualified class name of the
370 * <code>ImageReader</code> or <code>ImageWriter</code> plug-in
371 * associated with this service provider.
372 *
373 * @return the class name, as a non-<code>null</code>
374 * <code>String</code>.
375 */
376 public String getPluginClassName() {
377 return pluginClassName;
378 }
379
380 /**
381 * Returns <code>true</code> if the standard metadata format is
382 * among the document formats recognized by the
383 * <code>getAsTree</code> and <code>setFromTree</code> methods on
384 * the stream metadata objects produced or consumed by this
385 * plug-in.
386 *
387 * @return <code>true</code> if the standard format is supported
388 * for stream metadata.
389 */
390 public boolean isStandardStreamMetadataFormatSupported() {
391 return supportsStandardStreamMetadataFormat;
392 }
393
394 /**
395 * Returns the name of the "native" stream metadata format for
396 * this plug-in, which typically allows for lossless encoding and
397 * transmission of the stream metadata stored in the format handled by
398 * this plug-in. If no such format is supported,
399 * <code>null</code>will be returned.
400 *
401 * <p> The default implementation returns the
402 * <code>nativeStreamMetadataFormatName</code> instance variable,
403 * which is typically set by the constructor.
404 *
405 * @return the name of the native stream metadata format, or
406 * <code>null</code>.
407 *
408 */
409 public String getNativeStreamMetadataFormatName() {
410 return nativeStreamMetadataFormatName;
411 }
412
413 /**
414 * Returns an array of <code>String</code>s containing the names
415 * of additional document formats, other than the native and
416 * standard formats, recognized by the
417 * <code>getAsTree</code> and <code>setFromTree</code> methods on
418 * the stream metadata objects produced or consumed by this
419 * plug-in.
420 *
421 * <p> If the plug-in does not handle metadata, null should be
422 * returned.
423 *
424 * <p> The set of formats may differ according to the particular
425 * images being read or written; this method should indicate all
426 * the additional formats supported by the plug-in under any
427 * circumstances.
428 *
429 * <p> The default implementation returns a clone of the
430 * <code>extraStreamMetadataFormatNames</code> instance variable,
431 * which is typically set by the constructor.
432 *
433 * @return an array of <code>String</code>s, or null.
434 *
435 * @see IIOMetadata#getMetadataFormatNames
436 * @see #getExtraImageMetadataFormatNames
437 * @see #getNativeStreamMetadataFormatName
438 */
439 public String[] getExtraStreamMetadataFormatNames() {
440 return extraStreamMetadataFormatNames == null ? null
441 : (String[]) extraStreamMetadataFormatNames.clone();
442 }
443
444 /**
445 * Returns <code>true</code> if the standard metadata format is
446 * among the document formats recognized by the
447 * <code>getAsTree</code> and <code>setFromTree</code> methods on
448 * the image metadata objects produced or consumed by this
449 * plug-in.
450 *
451 * @return <code>true</code> if the standard format is supported
452 * for image metadata.
453 */
454 public boolean isStandardImageMetadataFormatSupported() {
455 return supportsStandardImageMetadataFormat;
456 }
457
458 /**
459 * Returns the name of the "native" image metadata format for
460 * this plug-in, which typically allows for lossless encoding and
461 * transmission of the image metadata stored in the format handled by
462 * this plug-in. If no such format is supported,
463 * <code>null</code>will be returned.
464 *
465 * <p> The default implementation returns the
466 * <code>nativeImageMetadataFormatName</code> instance variable,
467 * which is typically set by the constructor.
468 *
469 * @return the name of the native image metadata format, or
470 * <code>null</code>.
471 *
472 * @see #getExtraImageMetadataFormatNames
473 */
474 public String getNativeImageMetadataFormatName() {
475 return nativeImageMetadataFormatName;
476 }
477
478 /**
479 * Returns an array of <code>String</code>s containing the names
480 * of additional document formats, other than the native and
481 * standard formats, recognized by the
482 * <code>getAsTree</code> and <code>setFromTree</code> methods on
483 * the image metadata objects produced or consumed by this
484 * plug-in.
485 *
486 * <p> If the plug-in does not handle image metadata, null should
487 * be returned.
488 *
489 * <p> The set of formats may differ according to the particular
490 * images being read or written; this method should indicate all
491 * the additional formats supported by the plug-in under any circumstances.
492 *
493 * <p> The default implementation returns a clone of the
494 * <code>extraImageMetadataFormatNames</code> instance variable,
495 * which is typically set by the constructor.
496 *
497 * @return an array of <code>String</code>s, or null.
498 *
499 * @see IIOMetadata#getMetadataFormatNames
500 * @see #getExtraStreamMetadataFormatNames
501 * @see #getNativeImageMetadataFormatName
502 */
503 public String[] getExtraImageMetadataFormatNames() {
504 return extraImageMetadataFormatNames == null ? null
505 : (String[]) extraImageMetadataFormatNames.clone();
506 }
507
508 /**
509 * Returns an <code>IIOMetadataFormat</code> object describing the
510 * given stream metadata format, or <code>null</code> if no
511 * description is available. The supplied name must be the native
512 * stream metadata format name, the standard metadata format name,
513 * or one of those returned by
514 * <code>getExtraStreamMetadataFormatNames</code>.
515 *
516 * @param formatName the desired stream metadata format.
517 *
518 * @return an <code>IIOMetadataFormat</code> object.
519 *
520 * @exception IllegalArgumentException if <code>formatName</code>
521 * is <code>null</code> or is not a supported name.
522 */
523 public IIOMetadataFormat getStreamMetadataFormat(String formatName) {
524 return getMetadataFormat(formatName,
525 supportsStandardStreamMetadataFormat,
526 nativeStreamMetadataFormatName,
527 nativeStreamMetadataFormatClassName,
528 extraStreamMetadataFormatNames,
529 extraStreamMetadataFormatClassNames);
530 }
531
532 /**
533 * Returns an <code>IIOMetadataFormat</code> object describing the
534 * given image metadata format, or <code>null</code> if no
535 * description is available. The supplied name must be the native
536 * iamge metadata format name, the standard metadata format name,
537 * or one of those returned by
538 * <code>getExtraImageMetadataFormatNames</code>.
539 *
540 * @param formatName the desired image metadata format.
541 *
542 * @return an <code>IIOMetadataFormat</code> object.
543 *
544 * @exception IllegalArgumentException if <code>formatName</code>
545 * is <code>null</code> or is not a supported name.
546 */
547 public IIOMetadataFormat getImageMetadataFormat(String formatName) {
548 return getMetadataFormat(formatName,
549 supportsStandardImageMetadataFormat,
550 nativeImageMetadataFormatName,
551 nativeImageMetadataFormatClassName,
552 extraImageMetadataFormatNames,
553 extraImageMetadataFormatClassNames);
554 }
555
556 private IIOMetadataFormat getMetadataFormat(String formatName,
557 boolean supportsStandard, String nativeName,
558 String nativeClassName, String[] extraNames,
559 String[] extraClassNames) {
560 if (formatName == null) {
561 throw new IllegalArgumentException("formatName == null!");
562 }
563 if (supportsStandard
564 && formatName
565 .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
566
567 return IIOMetadataFormatImpl.getStandardFormatInstance();
568 }
569 String formatClassName = null;
570 if (formatName.equals(nativeName)) {
571 formatClassName = nativeClassName;
572 } else if (extraNames != null) {
573 for (int i = 0; i < extraNames.length; i++) {
574 if (formatName.equals(extraNames[i])) {
575 formatClassName = extraClassNames[i];
576 break; // out of for
577 }
578 }
579 }
580 if (formatClassName == null) {
581 throw new IllegalArgumentException(
582 "Unsupported format name");
583 }
584 try {
585 Class cls = Class.forName(formatClassName, true,
586 ClassLoader.getSystemClassLoader());
587 Method meth = cls.getMethod("getInstance");
588 return (IIOMetadataFormat) meth.invoke(null);
589 } catch (Exception e) {
590 RuntimeException ex = new IllegalStateException(
591 "Can't obtain format");
592 ex.initCause(e);
593 throw ex;
594 }
595 }
596 }
|