1 /* 2 * Copyright (c) 2000, 2005, 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 java.lang.reflect.Constructor; 30 import java.lang.reflect.Method; 31 import java.util.Arrays; 32 import java.util.Iterator; 33 import javax.imageio.ImageReader; 34 import javax.imageio.metadata.IIOMetadata; 35 import javax.imageio.metadata.IIOMetadataFormat; 36 import javax.imageio.metadata.IIOMetadataFormatImpl; 37 import javax.imageio.stream.ImageInputStream; 38 39 /** 40 * A superclass containing instance variables and methods common to 41 * <code>ImageReaderSpi</code> and <code>ImageWriterSpi</code>. 42 * 43 * @see IIORegistry 44 * @see ImageReaderSpi 45 * @see ImageWriterSpi 46 * 47 */ 48 public abstract class ImageReaderWriterSpi extends IIOServiceProvider { 49 50 /** 51 * An array of strings to be returned from 52 * <code>getFormatNames</code>, initially <code>null</code>. 53 * Constructors should set this to a non-<code>null</code> value. 54 */ 55 protected String[] names = null; 56 57 /** 58 * An array of strings to be returned from 59 * <code>getFileSuffixes</code>, initially <code>null</code>. 60 */ 61 protected String[] suffixes = null; 62 63 /** 64 * An array of strings to be returned from 65 * <code>getMIMETypes</code>, initially <code>null</code>. 66 */ 67 protected String[] MIMETypes = null; 68 69 /** 70 * A <code>String</code> containing the name of the associated 71 * plug-in class, initially <code>null</code>. 72 */ 73 protected String pluginClassName = null; 74 75 /** 76 * A boolean indicating whether this plug-in supports the 77 * standard metadata format for stream metadata, initially 78 * <code>false</code>. 79 */ 80 protected boolean supportsStandardStreamMetadataFormat = false; 81 82 /** 83 * A <code>String</code> containing the name of the native stream 84 * metadata format supported by this plug-in, initially 85 * <code>null</code>. 86 */ 87 protected String nativeStreamMetadataFormatName = null; 88 89 /** 90 * A <code>String</code> containing the class name of the native 91 * stream metadata format supported by this plug-in, initially 92 * <code>null</code>. 93 */ 94 protected String nativeStreamMetadataFormatClassName = null; 95 96 /** 97 * An array of <code>String</code>s containing the names of any 98 * additional stream metadata formats supported by this plug-in, 99 * initially <code>null</code>. 100 */ 101 protected String[] extraStreamMetadataFormatNames = null; 102 103 /** 104 * An array of <code>String</code>s containing the class names of 105 * any additional stream metadata formats supported by this plug-in, 106 * initially <code>null</code>. 107 */ 108 protected String[] extraStreamMetadataFormatClassNames = null; 109 110 /** 111 * A boolean indicating whether this plug-in supports the 112 * standard metadata format for image metadata, initially 113 * <code>false</code>. 114 */ 115 protected boolean supportsStandardImageMetadataFormat = false; 116 117 /** 118 * A <code>String</code> containing the name of the 119 * native stream metadata format supported by this plug-in, 120 * initially <code>null</code>. 121 */ 122 protected String nativeImageMetadataFormatName = null; 123 124 /** 125 * A <code>String</code> containing the class name of the 126 * native stream metadata format supported by this plug-in, 127 * initially <code>null</code>. 128 */ 129 protected String nativeImageMetadataFormatClassName = null; 130 131 /** 132 * An array of <code>String</code>s containing the names of any 133 * additional image metadata formats supported by this plug-in, 134 * initially <code>null</code>. 135 */ 136 protected String[] extraImageMetadataFormatNames = null; 137 138 /** 139 * An array of <code>String</code>s containing the class names of 140 * any additional image metadata formats supported by this 141 * plug-in, initially <code>null</code>. 142 */ 143 protected String[] extraImageMetadataFormatClassNames = null; 144 145 /** 146 * Constructs an <code>ImageReaderWriterSpi</code> with a given 147 * set of values. 148 * 149 * @param vendorName the vendor name, as a non-<code>null</code> 150 * <code>String</code>. 151 * @param version a version identifier, as a non-<code>null</code> 152 * <code>String</code>. 153 * @param names a non-<code>null</code> array of 154 * <code>String</code>s indicating the format names. At least one 155 * entry must be present. 156 * @param suffixes an array of <code>String</code>s indicating the 157 * common file suffixes. If no suffixes are defined, 158 * <code>null</code> should be supplied. An array of length 0 159 * will be normalized to <code>null</code>. 160 * @param MIMETypes an array of <code>String</code>s indicating 161 * the format's MIME types. If no MIME types are defined, 162 * <code>null</code> should be supplied. An array of length 0 163 * will be normalized to <code>null</code>. 164 * @param pluginClassName the fully-qualified name of the 165 * associated <code>ImageReader</code> or <code>ImageWriter</code> 166 * class, as a non-<code>null</code> <code>String</code>. 167 * @param supportsStandardStreamMetadataFormat a 168 * <code>boolean</code> that indicates whether a stream metadata 169 * object can use trees described by the standard metadata format. 170 * @param nativeStreamMetadataFormatName a 171 * <code>String</code>, or <code>null</code>, to be returned from 172 * <code>getNativeStreamMetadataFormatName</code>. 173 * @param nativeStreamMetadataFormatClassName a 174 * <code>String</code>, or <code>null</code>, to be used to instantiate 175 * a metadata format object to be returned from 176 * <code>getNativeStreamMetadataFormat</code>. 177 * @param extraStreamMetadataFormatNames an array of 178 * <code>String</code>s, or <code>null</code>, to be returned from 179 * <code>getExtraStreamMetadataFormatNames</code>. An array of length 180 * 0 is normalized to <code>null</code>. 181 * @param extraStreamMetadataFormatClassNames an array of 182 * <code>String</code>s, or <code>null</code>, to be used to instantiate 183 * a metadata format object to be returned from 184 * <code>getStreamMetadataFormat</code>. An array of length 185 * 0 is normalized to <code>null</code>. 186 * @param supportsStandardImageMetadataFormat a 187 * <code>boolean</code> that indicates whether an image metadata 188 * object can use trees described by the standard metadata format. 189 * @param nativeImageMetadataFormatName a 190 * <code>String</code>, or <code>null</code>, to be returned from 191 * <code>getNativeImageMetadataFormatName</code>. 192 * @param nativeImageMetadataFormatClassName a 193 * <code>String</code>, or <code>null</code>, to be used to instantiate 194 * a metadata format object to be returned from 195 * <code>getNativeImageMetadataFormat</code>. 196 * @param extraImageMetadataFormatNames an array of 197 * <code>String</code>s to be returned from 198 * <code>getExtraImageMetadataFormatNames</code>. An array of length 0 199 * is normalized to <code>null</code>. 200 * @param extraImageMetadataFormatClassNames an array of 201 * <code>String</code>s, or <code>null</code>, to be used to instantiate 202 * a metadata format object to be returned from 203 * <code>getImageMetadataFormat</code>. An array of length 204 * 0 is normalized to <code>null</code>. 205 * 206 * @exception IllegalArgumentException if <code>vendorName</code> 207 * is <code>null</code>. 208 * @exception IllegalArgumentException if <code>version</code> 209 * is <code>null</code>. 210 * @exception IllegalArgumentException if <code>names</code> 211 * is <code>null</code> or has length 0. 212 * @exception IllegalArgumentException if <code>pluginClassName</code> 213 * is <code>null</code>. 214 */ 215 public ImageReaderWriterSpi(String vendorName, 216 String version, 217 String[] names, 218 String[] suffixes, 219 String[] MIMETypes, 220 String pluginClassName, 221 boolean supportsStandardStreamMetadataFormat, 222 String nativeStreamMetadataFormatName, 223 String nativeStreamMetadataFormatClassName, 224 String[] extraStreamMetadataFormatNames, 225 String[] extraStreamMetadataFormatClassNames, 226 boolean supportsStandardImageMetadataFormat, 227 String nativeImageMetadataFormatName, 228 String nativeImageMetadataFormatClassName, 229 String[] extraImageMetadataFormatNames, 230 String[] extraImageMetadataFormatClassNames) { 231 super(vendorName, version); 232 if (names == null) { 233 throw new IllegalArgumentException("names == null!"); 234 } 235 if (names.length == 0) { 236 throw new IllegalArgumentException("names.length == 0!"); 237 } 238 if (pluginClassName == null) { 239 throw new IllegalArgumentException("pluginClassName == null!"); 240 } 241 242 this.names = (String[])names.clone(); 243 // If length == 0, leave it null 244 if (suffixes != null && suffixes.length > 0) { 245 this.suffixes = (String[])suffixes.clone(); 246 } 247 // If length == 0, leave it null 248 if (MIMETypes != null && MIMETypes.length > 0) { 249 this.MIMETypes = (String[])MIMETypes.clone(); 250 } 251 this.pluginClassName = pluginClassName; 252 253 this.supportsStandardStreamMetadataFormat = 254 supportsStandardStreamMetadataFormat; 255 this.nativeStreamMetadataFormatName = nativeStreamMetadataFormatName; 256 this.nativeStreamMetadataFormatClassName = 257 nativeStreamMetadataFormatClassName; 258 // If length == 0, leave it null 259 if (extraStreamMetadataFormatNames != null && 260 extraStreamMetadataFormatNames.length > 0) { 261 this.extraStreamMetadataFormatNames = 262 (String[])extraStreamMetadataFormatNames.clone(); 263 } 264 // If length == 0, leave it null 265 if (extraStreamMetadataFormatClassNames != null && 266 extraStreamMetadataFormatClassNames.length > 0) { 267 this.extraStreamMetadataFormatClassNames = 268 (String[])extraStreamMetadataFormatClassNames.clone(); 269 } 270 this.supportsStandardImageMetadataFormat = 271 supportsStandardImageMetadataFormat; 272 this.nativeImageMetadataFormatName = nativeImageMetadataFormatName; 273 this.nativeImageMetadataFormatClassName = 274 nativeImageMetadataFormatClassName; 275 // If length == 0, leave it null 276 if (extraImageMetadataFormatNames != null && 277 extraImageMetadataFormatNames.length > 0) { 278 this.extraImageMetadataFormatNames = 279 (String[])extraImageMetadataFormatNames.clone(); 280 } 281 // If length == 0, leave it null 282 if (extraImageMetadataFormatClassNames != null && 283 extraImageMetadataFormatClassNames.length > 0) { 284 this.extraImageMetadataFormatClassNames = 285 (String[])extraImageMetadataFormatClassNames.clone(); 286 } 287 } 288 289 /** 290 * Constructs a blank <code>ImageReaderWriterSpi</code>. It is up 291 * to the subclass to initialize instance variables and/or 292 * override method implementations in order to provide working 293 * versions of all methods. 294 */ 295 public ImageReaderWriterSpi() { 296 } 297 298 /** 299 * Returns an array of <code>String</code>s containing 300 * human-readable names for the formats that are generally usable 301 * by the <code>ImageReader</code> or <code>ImageWriter</code> 302 * implementation associated with this service provider. For 303 * example, a single <code>ImageReader</code> might be able to 304 * process both PBM and PNM files. 305 * 306 * @return a non-<code>null</code> array of <code>String</code>s 307 * or length at least 1 containing informal format names 308 * associated with this reader or writer. 309 */ 310 public String[] getFormatNames() { 311 return (String[])names.clone(); 312 } 313 314 /** 315 * Returns an array of <code>String</code>s containing a list of 316 * file suffixes associated with the formats that are generally 317 * usable by the <code>ImageReader</code> or 318 * <code>ImageWriter</code> implementation associated with this 319 * service provider. For example, a single 320 * <code>ImageReader</code> might be able to process files with 321 * '.pbm' and '.pnm' suffixes, or both '.jpg' and '.jpeg' 322 * suffixes. If there are no known file suffixes, 323 * <code>null</code> will be returned. 324 * 325 * <p> Returning a particular suffix does not guarantee that files 326 * with that suffix can be processed; it merely indicates that it 327 * may be worthwhile attempting to decode or encode such files 328 * using this service provider. 329 * 330 * @return an array of <code>String</code>s or length at least 1 331 * containing common file suffixes associated with this reader or 332 * writer, or <code>null</code>. 333 */ 334 public String[] getFileSuffixes() { 335 return suffixes == null ? null : (String[])suffixes.clone(); 336 } 337 338 /** 339 * Returns an array of <code>String</code>s containing a list of 340 * MIME types associated with the formats that are generally 341 * usable by the <code>ImageReader</code> or 342 * <code>ImageWriter</code> implementation associated with this 343 * service provider. 344 * 345 * <p> Ideally, only a single MIME type would be required in order 346 * to describe a particular format. However, for several reasons 347 * it is necessary to associate a list of types with each service 348 * provider. First, many common image file formats do not have 349 * standard MIME types, so a list of commonly used unofficial 350 * names will be required, such as <code>image/x-pbm</code> and 351 * <code>image/x-portable-bitmap</code>. Some file formats have 352 * official MIME types but may sometimes be referred to using 353 * their previous unofficial designations, such as 354 * <code>image/x-png</code> instead of the official 355 * <code>image/png</code>. Finally, a single service provider may 356 * be capable of parsing multiple distinct types from the MIME 357 * point of view, for example <code>image/x-xbitmap</code> and 358 * <code>image/x-xpixmap</code>. 359 * 360 * <p> Returning a particular MIME type does not guarantee that 361 * files claiming to be of that type can be processed; it merely 362 * indicates that it may be worthwhile attempting to decode or 363 * encode such files using this service provider. 364 * 365 * @return an array of <code>String</code>s or length at least 1 366 * containing MIME types associated with this reader or writer, or 367 * <code>null</code>. 368 */ 369 public String[] getMIMETypes() { 370 return MIMETypes == null ? null : (String[])MIMETypes.clone(); 371 } 372 373 /** 374 * Returns the fully-qualified class name of the 375 * <code>ImageReader</code> or <code>ImageWriter</code> plug-in 376 * associated with this service provider. 377 * 378 * @return the class name, as a non-<code>null</code> 379 * <code>String</code>. 380 */ 381 public String getPluginClassName() { 382 return pluginClassName; 383 } 384 385 /** 386 * Returns <code>true</code> if the standard metadata format is 387 * among the document formats recognized by the 388 * <code>getAsTree</code> and <code>setFromTree</code> methods on 389 * the stream metadata objects produced or consumed by this 390 * plug-in. 391 * 392 * @return <code>true</code> if the standard format is supported 393 * for stream metadata. 394 */ 395 public boolean isStandardStreamMetadataFormatSupported() { 396 return supportsStandardStreamMetadataFormat; 397 } 398 399 /** 400 * Returns the name of the "native" stream metadata format for 401 * this plug-in, which typically allows for lossless encoding and 402 * transmission of the stream metadata stored in the format handled by 403 * this plug-in. If no such format is supported, 404 * <code>null</code>will be returned. 405 * 406 * <p> The default implementation returns the 407 * <code>nativeStreamMetadataFormatName</code> instance variable, 408 * which is typically set by the constructor. 409 * 410 * @return the name of the native stream metadata format, or 411 * <code>null</code>. 412 * 413 */ 414 public String getNativeStreamMetadataFormatName() { 415 return nativeStreamMetadataFormatName; 416 } 417 418 /** 419 * Returns an array of <code>String</code>s containing the names 420 * of additional document formats, other than the native and 421 * standard formats, recognized by the 422 * <code>getAsTree</code> and <code>setFromTree</code> methods on 423 * the stream metadata objects produced or consumed by this 424 * plug-in. 425 * 426 * <p> If the plug-in does not handle metadata, null should be 427 * returned. 428 * 429 * <p> The set of formats may differ according to the particular 430 * images being read or written; this method should indicate all 431 * the additional formats supported by the plug-in under any 432 * circumstances. 433 * 434 * <p> The default implementation returns a clone of the 435 * <code>extraStreamMetadataFormatNames</code> instance variable, 436 * which is typically set by the constructor. 437 * 438 * @return an array of <code>String</code>s, or null. 439 * 440 * @see IIOMetadata#getMetadataFormatNames 441 * @see #getExtraImageMetadataFormatNames 442 * @see #getNativeStreamMetadataFormatName 443 */ 444 public String[] getExtraStreamMetadataFormatNames() { 445 return extraStreamMetadataFormatNames == null ? 446 null : (String[])extraStreamMetadataFormatNames.clone(); 447 } 448 449 /** 450 * Returns <code>true</code> if the standard metadata format is 451 * among the document formats recognized by the 452 * <code>getAsTree</code> and <code>setFromTree</code> methods on 453 * the image metadata objects produced or consumed by this 454 * plug-in. 455 * 456 * @return <code>true</code> if the standard format is supported 457 * for image metadata. 458 */ 459 public boolean isStandardImageMetadataFormatSupported() { 460 return supportsStandardImageMetadataFormat; 461 } 462 463 /** 464 * Returns the name of the "native" image metadata format for 465 * this plug-in, which typically allows for lossless encoding and 466 * transmission of the image metadata stored in the format handled by 467 * this plug-in. If no such format is supported, 468 * <code>null</code>will be returned. 469 * 470 * <p> The default implementation returns the 471 * <code>nativeImageMetadataFormatName</code> instance variable, 472 * which is typically set by the constructor. 473 * 474 * @return the name of the native image metadata format, or 475 * <code>null</code>. 476 * 477 * @see #getExtraImageMetadataFormatNames 478 */ 479 public String getNativeImageMetadataFormatName() { 480 return nativeImageMetadataFormatName; 481 } 482 483 /** 484 * Returns an array of <code>String</code>s containing the names 485 * of additional document formats, other than the native and 486 * standard formats, recognized by the 487 * <code>getAsTree</code> and <code>setFromTree</code> methods on 488 * the image metadata objects produced or consumed by this 489 * plug-in. 490 * 491 * <p> If the plug-in does not handle image metadata, null should 492 * be returned. 493 * 494 * <p> The set of formats may differ according to the particular 495 * images being read or written; this method should indicate all 496 * the additional formats supported by the plug-in under any circumstances. 497 * 498 * <p> The default implementation returns a clone of the 499 * <code>extraImageMetadataFormatNames</code> instance variable, 500 * which is typically set by the constructor. 501 * 502 * @return an array of <code>String</code>s, or null. 503 * 504 * @see IIOMetadata#getMetadataFormatNames 505 * @see #getExtraStreamMetadataFormatNames 506 * @see #getNativeImageMetadataFormatName 507 */ 508 public String[] getExtraImageMetadataFormatNames() { 509 return extraImageMetadataFormatNames == null ? 510 null : (String[])extraImageMetadataFormatNames.clone(); 511 } 512 513 /** 514 * Returns an <code>IIOMetadataFormat</code> object describing the 515 * given stream metadata format, or <code>null</code> if no 516 * description is available. The supplied name must be the native 517 * stream metadata format name, the standard metadata format name, 518 * or one of those returned by 519 * <code>getExtraStreamMetadataFormatNames</code>. 520 * 521 * @param formatName the desired stream metadata format. 522 * 523 * @return an <code>IIOMetadataFormat</code> object. 524 * 525 * @exception IllegalArgumentException if <code>formatName</code> 526 * is <code>null</code> or is not a supported name. 527 */ 528 public IIOMetadataFormat getStreamMetadataFormat(String formatName) { 529 return getMetadataFormat(formatName, 530 supportsStandardStreamMetadataFormat, 531 nativeStreamMetadataFormatName, 532 nativeStreamMetadataFormatClassName, 533 extraStreamMetadataFormatNames, 534 extraStreamMetadataFormatClassNames); 535 } 536 537 /** 538 * Returns an <code>IIOMetadataFormat</code> object describing the 539 * given image metadata format, or <code>null</code> if no 540 * description is available. The supplied name must be the native 541 * image metadata format name, the standard metadata format name, 542 * or one of those returned by 543 * <code>getExtraImageMetadataFormatNames</code>. 544 * 545 * @param formatName the desired image metadata format. 546 * 547 * @return an <code>IIOMetadataFormat</code> object. 548 * 549 * @exception IllegalArgumentException if <code>formatName</code> 550 * is <code>null</code> or is not a supported name. 551 */ 552 public IIOMetadataFormat getImageMetadataFormat(String formatName) { 553 return getMetadataFormat(formatName, 554 supportsStandardImageMetadataFormat, 555 nativeImageMetadataFormatName, 556 nativeImageMetadataFormatClassName, 557 extraImageMetadataFormatNames, 558 extraImageMetadataFormatClassNames); 559 } 560 561 private IIOMetadataFormat getMetadataFormat(String formatName, 562 boolean supportsStandard, 563 String nativeName, 564 String nativeClassName, 565 String [] extraNames, 566 String [] extraClassNames) { 567 if (formatName == null) { 568 throw new IllegalArgumentException("formatName == null!"); 569 } 570 if (supportsStandard && formatName.equals 571 (IIOMetadataFormatImpl.standardMetadataFormatName)) { 572 573 return IIOMetadataFormatImpl.getStandardFormatInstance(); 574 } 575 String formatClassName = null; 576 if (formatName.equals(nativeName)) { 577 formatClassName = nativeClassName; 578 } else if (extraNames != null) { 579 for (int i = 0; i < extraNames.length; i++) { 580 if (formatName.equals(extraNames[i])) { 581 formatClassName = extraClassNames[i]; 582 break; // out of for 583 } 584 } 585 } 586 if (formatClassName == null) { 587 throw new IllegalArgumentException("Unsupported format name"); 588 } 589 try { 590 Class cls = Class.forName(formatClassName, true, 591 ClassLoader.getSystemClassLoader()); 592 Method meth = cls.getMethod("getInstance"); 593 return (IIOMetadataFormat) meth.invoke(null); 594 } catch (Exception e) { 595 RuntimeException ex = 596 new IllegalStateException ("Can't obtain format"); 597 ex.initCause(e); 598 throw ex; 599 } 600 } 601 }