1619 lines · 57.4 KB · Java
RawDownload
/* * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.imageio; import java.awt.image.BufferedImage;import java.awt.image.RenderedImage;import java.io.File;import java.io.FilePermission;import java.io.InputStream;import java.io.IOException;import java.io.OutputStream;import java.lang.reflect.Method;import java.net.URL;import java.security.AccessController;import java.util.Arrays;import java.util.Collections;import java.util.HashSet;import java.util.Iterator;import java.util.NoSuchElementException;import java.util.Set;import javax.imageio.spi.IIORegistry;import javax.imageio.spi.ImageReaderSpi;import javax.imageio.spi.ImageReaderWriterSpi;import javax.imageio.spi.ImageWriterSpi;import javax.imageio.spi.ImageInputStreamSpi;import javax.imageio.spi.ImageOutputStreamSpi;import javax.imageio.spi.ImageTranscoderSpi;import javax.imageio.spi.ServiceRegistry;import javax.imageio.stream.ImageInputStream;import javax.imageio.stream.ImageOutputStream;import sun.awt.AppContext;import sun.security.action.GetPropertyAction; /** * A class containing static convenience methods for locating * <code>ImageReader</code>s and <code>ImageWriter</code>s, and * performing simple encoding and decoding. * */public final class ImageIO {     private static final IIORegistry theRegistry =        IIORegistry.getDefaultInstance();     /**     * Constructor is private to prevent instantiation.     */    private ImageIO() {}     /**     * Scans for plug-ins on the application class path,     * loads their service provider classes, and registers a service     * provider instance for each one found with the     * <code>IIORegistry</code>.     *     * <p>This method is needed because the application class path can     * theoretically change, or additional plug-ins may become available.     * Rather than re-scanning the classpath on every invocation of the     * API, the class path is scanned automatically only on the first     * invocation. Clients can call this method to prompt a re-scan.     * Thus this method need only be invoked by sophisticated applications     * which dynamically make new plug-ins available at runtime.     *     * <p> The <code>getResources</code> method of the context     * <code>ClassLoader</code> is used locate JAR files containing     * files named     * <code>META-INF/services/javax.imageio.spi.</code><i>classname</i>,     * where <i>classname</i> is one of <code>ImageReaderSpi</code>,     * <code>ImageWriterSpi</code>, <code>ImageTranscoderSpi</code>,     * <code>ImageInputStreamSpi</code>, or     * <code>ImageOutputStreamSpi</code>, along the application class     * path.     *     * <p> The contents of the located files indicate the names of     * actual implementation classes which implement the     * aforementioned service provider interfaces; the default class     * loader is then used to load each of these classes and to     * instantiate an instance of each class, which is then placed     * into the registry for later retrieval.     *     * <p> The exact set of locations searched depends on the     * implementation of the Java runtime enviroment.     *     * @see ClassLoader#getResources     */    public static void scanForPlugins() {        theRegistry.registerApplicationClasspathSpis();    }     // ImageInputStreams     /**     * A class to hold information about caching.  Each     * <code>ThreadGroup</code> will have its own copy     * via the <code>AppContext</code> mechanism.     */    static class CacheInfo {        boolean useCache = true;        File cacheDirectory = null;        Boolean hasPermission = null;         public CacheInfo() {}         public boolean getUseCache() {            return useCache;        }         public void setUseCache(boolean useCache) {            this.useCache = useCache;        }         public File getCacheDirectory() {            return cacheDirectory;        }         public void setCacheDirectory(File cacheDirectory) {            this.cacheDirectory = cacheDirectory;        }         public Boolean getHasPermission() {            return hasPermission;        }         public void setHasPermission(Boolean hasPermission) {            this.hasPermission = hasPermission;        }    }     /**     * Returns the <code>CacheInfo</code> object associated with this     * <code>ThreadGroup</code>.     */    private static synchronized CacheInfo getCacheInfo() {        AppContext context = AppContext.getAppContext();        CacheInfo info = (CacheInfo)context.get(CacheInfo.class);        if (info == null) {            info = new CacheInfo();            context.put(CacheInfo.class, info);        }        return info;    }     /**     * Returns the default temporary (cache) directory as defined by the     * java.io.tmpdir system property.     */    private static String getTempDir() {        GetPropertyAction a = new GetPropertyAction("java.io.tmpdir");        return (String)AccessController.doPrivileged(a);    }     /**     * Determines whether the caller has write access to the cache     * directory, stores the result in the <code>CacheInfo</code> object,     * and returns the decision.  This method helps to prevent mysterious     * SecurityExceptions to be thrown when this convenience class is used     * in an applet, for example.     */    private static boolean hasCachePermission() {        Boolean hasPermission = getCacheInfo().getHasPermission();         if (hasPermission != null) {            return hasPermission.booleanValue();        } else {            try {                SecurityManager security = System.getSecurityManager();                if (security != null) {                    File cachedir = getCacheDirectory();                    String cachepath;                     if (cachedir != null) {                        cachepath = cachedir.getPath();                    } else {                        cachepath = getTempDir();                         if (cachepath == null || cachepath.isEmpty()) {                            getCacheInfo().setHasPermission(Boolean.FALSE);                            return false;                        }                    }                     // we have to check whether we can read, write,                    // and delete cache files.                    // So, compose cache file path and check it.                    String filepath = cachepath;                    if (!filepath.endsWith(File.separator)) {                        filepath += File.separator;                    }                    filepath += "*";                     security.checkPermission(new FilePermission(filepath, "read, write, delete"));                }            } catch (SecurityException e) {                getCacheInfo().setHasPermission(Boolean.FALSE);                return false;            }             getCacheInfo().setHasPermission(Boolean.TRUE);            return true;        }    }     /**     * Sets a flag indicating whether a disk-based cache file should     * be used when creating <code>ImageInputStream</code>s and     * <code>ImageOutputStream</code>s.     *     * <p> When reading from a standard <code>InputStream</code>>, it     * may be necessary to save previously read information in a cache     * since the underlying stream does not allow data to be re-read.     * Similarly, when writing to a standard     * <code>OutputStream</code>, a cache may be used to allow a     * previously written value to be changed before flushing it to     * the final destination.     *     * <p> The cache may reside in main memory or on disk.  Setting     * this flag to <code>false</code> disallows the use of disk for     * future streams, which may be advantageous when working with     * small images, as the overhead of creating and destroying files     * is removed.     *     * <p> On startup, the value is set to <code>true</code>.     *     * @param useCache a <code>boolean</code> indicating whether a     * cache file should be used, in cases where it is optional.     *     * @see #getUseCache     */    public static void setUseCache(boolean useCache) {        getCacheInfo().setUseCache(useCache);    }     /**     * Returns the current value set by <code>setUseCache</code>, or     * <code>true</code> if no explicit setting has been made.     *     * @return true if a disk-based cache may be used for     * <code>ImageInputStream</code>s and     * <code>ImageOutputStream</code>s.     *     * @see #setUseCache     */    public static boolean getUseCache() {        return getCacheInfo().getUseCache();    }     /**     * Sets the directory where cache files are to be created.  A     * value of <code>null</code> indicates that the system-dependent     * default temporary-file directory is to be used.  If     * <code>getUseCache</code> returns false, this value is ignored.     *     * @param cacheDirectory a <code>File</code> specifying a directory.     *     * @see File#createTempFile(String, String, File)     *     * @exception SecurityException if the security manager denies     * access to the directory.     * @exception IllegalArgumentException if <code>cacheDir</code> is     * non-<code>null</code> but is not a directory.     *     * @see #getCacheDirectory     */    public static void setCacheDirectory(File cacheDirectory) {        if ((cacheDirectory != null) && !(cacheDirectory.isDirectory())) {            throw new IllegalArgumentException("Not a directory!");        }        getCacheInfo().setCacheDirectory(cacheDirectory);        getCacheInfo().setHasPermission(null);    }     /**     * Returns the current value set by     * <code>setCacheDirectory</code>, or <code>null</code> if no     * explicit setting has been made.     *     * @return a <code>File</code> indicating the directory where     * cache files will be created, or <code>null</code> to indicate     * the system-dependent default temporary-file directory.     *     * @see #setCacheDirectory     */    public static File getCacheDirectory() {        return getCacheInfo().getCacheDirectory();    }     /**     * Returns an <code>ImageInputStream</code> that will take its     * input from the given <code>Object</code>.  The set of     * <code>ImageInputStreamSpi</code>s registered with the     * <code>IIORegistry</code> class is queried and the first one     * that is able to take input from the supplied object is used to     * create the returned <code>ImageInputStream</code>.  If no     * suitable <code>ImageInputStreamSpi</code> exists,     * <code>null</code> is returned.     *     * <p> The current cache settings from <code>getUseCache</code>and     * <code>getCacheDirectory</code> will be used to control caching.     *     * @param input an <code>Object</code> to be used as an input     * source, such as a <code>File</code>, readable     * <code>RandomAccessFile</code>, or <code>InputStream</code>.     *     * @return an <code>ImageInputStream</code>, or <code>null</code>.     *     * @exception IllegalArgumentException if <code>input</code>     * is <code>null</code>.     * @exception IOException if a cache file is needed but cannot be     * created.     *     * @see javax.imageio.spi.ImageInputStreamSpi     */    public static ImageInputStream createImageInputStream(Object input)        throws IOException {        if (input == null) {            throw new IllegalArgumentException("input == null!");        }         Iterator iter;        // Ensure category is present        try {            iter = theRegistry.getServiceProviders(ImageInputStreamSpi.class,                                                   true);        } catch (IllegalArgumentException e) {            return null;        }         boolean usecache = getUseCache() && hasCachePermission();         while (iter.hasNext()) {            ImageInputStreamSpi spi = (ImageInputStreamSpi)iter.next();            if (spi.getInputClass().isInstance(input)) {                try {                    return spi.createInputStreamInstance(input,                                                         usecache,                                                         getCacheDirectory());                } catch (IOException e) {                    throw new IIOException("Can't create cache file!", e);                }            }        }         return null;    }     // ImageOutputStreams     /**     * Returns an <code>ImageOutputStream</code> that will send its     * output to the given <code>Object</code>.  The set of     * <code>ImageOutputStreamSpi</code>s registered with the     * <code>IIORegistry</code> class is queried and the first one     * that is able to send output from the supplied object is used to     * create the returned <code>ImageOutputStream</code>.  If no     * suitable <code>ImageOutputStreamSpi</code> exists,     * <code>null</code> is returned.     *     * <p> The current cache settings from <code>getUseCache</code>and     * <code>getCacheDirectory</code> will be used to control caching.     *     * @param output an <code>Object</code> to be used as an output     * destination, such as a <code>File</code>, writable     * <code>RandomAccessFile</code>, or <code>OutputStream</code>.     *     * @return an <code>ImageOutputStream</code>, or     * <code>null</code>.     *     * @exception IllegalArgumentException if <code>output</code> is     * <code>null</code>.     * @exception IOException if a cache file is needed but cannot be     * created.     *     * @see javax.imageio.spi.ImageOutputStreamSpi     */    public static ImageOutputStream createImageOutputStream(Object output)        throws IOException {        if (output == null) {            throw new IllegalArgumentException("output == null!");        }         Iterator iter;        // Ensure category is present        try {            iter = theRegistry.getServiceProviders(ImageOutputStreamSpi.class,                                                   true);        } catch (IllegalArgumentException e) {            return null;        }         boolean usecache = getUseCache() && hasCachePermission();         while (iter.hasNext()) {            ImageOutputStreamSpi spi = (ImageOutputStreamSpi)iter.next();            if (spi.getOutputClass().isInstance(output)) {                try {                    return spi.createOutputStreamInstance(output,                                                          usecache,                                                          getCacheDirectory());                } catch (IOException e) {                    throw new IIOException("Can't create cache file!", e);                }            }        }         return null;    }     private static enum SpiInfo {        FORMAT_NAMES {            @Override            String[] info(ImageReaderWriterSpi spi) {                return spi.getFormatNames();            }        },        MIME_TYPES {            @Override            String[] info(ImageReaderWriterSpi spi) {                return spi.getMIMETypes();            }        },        FILE_SUFFIXES {            @Override            String[] info(ImageReaderWriterSpi spi) {                return spi.getFileSuffixes();            }        };         abstract String[] info(ImageReaderWriterSpi spi);    }     private static <S extends ImageReaderWriterSpi>        String[] getReaderWriterInfo(Class<S> spiClass, SpiInfo spiInfo)    {        // Ensure category is present        Iterator<S> iter;        try {            iter = theRegistry.getServiceProviders(spiClass, true);        } catch (IllegalArgumentException e) {            return new String[0];        }         HashSet<String> s = new HashSet<String>();        while (iter.hasNext()) {            ImageReaderWriterSpi spi = iter.next();            Collections.addAll(s, spiInfo.info(spi));        }         return s.toArray(new String[s.size()]);    }     // Readers     /**     * Returns an array of <code>String</code>s listing all of the     * informal format names understood by the current set of registered     * readers.     *     * @return an array of <code>String</code>s.     */    public static String[] getReaderFormatNames() {        return getReaderWriterInfo(ImageReaderSpi.class,                                   SpiInfo.FORMAT_NAMES);    }     /**     * Returns an array of <code>String</code>s listing all of the     * MIME types understood by the current set of registered     * readers.     *     * @return an array of <code>String</code>s.     */    public static String[] getReaderMIMETypes() {        return getReaderWriterInfo(ImageReaderSpi.class,                                   SpiInfo.MIME_TYPES);    }     /**

Lines 1–500 of 1619.