Path: blob/master/src/java.desktop/share/classes/javax/imageio/spi/IIORegistry.java
41154 views
/*1* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.imageio.spi;2627import java.security.PrivilegedAction;28import java.security.AccessController;29import java.util.HashMap;30import java.util.Iterator;31import java.util.Map;32import java.util.NoSuchElementException;33import java.util.Set;34import java.util.Vector;35import com.sun.imageio.spi.FileImageInputStreamSpi;36import com.sun.imageio.spi.FileImageOutputStreamSpi;37import com.sun.imageio.spi.InputStreamImageInputStreamSpi;38import com.sun.imageio.spi.OutputStreamImageOutputStreamSpi;39import com.sun.imageio.spi.RAFImageInputStreamSpi;40import com.sun.imageio.spi.RAFImageOutputStreamSpi;41import com.sun.imageio.plugins.gif.GIFImageReaderSpi;42import com.sun.imageio.plugins.gif.GIFImageWriterSpi;43import com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi;44import com.sun.imageio.plugins.jpeg.JPEGImageWriterSpi;45import com.sun.imageio.plugins.png.PNGImageReaderSpi;46import com.sun.imageio.plugins.png.PNGImageWriterSpi;47import com.sun.imageio.plugins.bmp.BMPImageReaderSpi;48import com.sun.imageio.plugins.bmp.BMPImageWriterSpi;49import com.sun.imageio.plugins.wbmp.WBMPImageReaderSpi;50import com.sun.imageio.plugins.wbmp.WBMPImageWriterSpi;51import com.sun.imageio.plugins.tiff.TIFFImageReaderSpi;52import com.sun.imageio.plugins.tiff.TIFFImageWriterSpi;53import sun.awt.AppContext;54import java.util.ServiceLoader;55import java.util.ServiceConfigurationError;5657/**58* A registry for Image I/O service provider instances. Service provider59* classes may be discovered at runtime by the mechanisms documented in60* {@link java.util.ServiceLoader ServiceLoader}.61*62* The intent is that it be relatively inexpensive to load and inspect63* all available Image I/O service provider classes.64* These classes may then be used to locate and instantiate65* more heavyweight classes that will perform actual work, in this66* case instances of {@code ImageReader},67* {@code ImageWriter}, {@code ImageTranscoder},68* {@code ImageInputStream}, and {@code ImageOutputStream}.69*70* Service providers included in the Java runtime are automatically71* loaded as soon as this class is instantiated.72*73* <p> When the {@code registerApplicationClasspathSpis} method74* is called, additional service provider instances will be discovered75* using {@link java.util.ServiceLoader ServiceLoader}.76*77* <p> It is also possible to manually add service providers not found78* automatically, as well as to remove those that are using the79* interfaces of the {@code ServiceRegistry} class. Thus80* the application may customize the contents of the registry as it81* sees fit.82*83* <p> For information on how to create and deploy service providers,84* refer to the documentation on {@link java.util.ServiceLoader ServiceLoader}85*/86public final class IIORegistry extends ServiceRegistry {8788/**89* A {@code Vector} containing the valid IIO registry90* categories (superinterfaces) to be used in the constructor.91*/92private static final Vector<Class<?>> initialCategories = new Vector<>(5);9394static {95initialCategories.add(ImageReaderSpi.class);96initialCategories.add(ImageWriterSpi.class);97initialCategories.add(ImageTranscoderSpi.class);98initialCategories.add(ImageInputStreamSpi.class);99initialCategories.add(ImageOutputStreamSpi.class);100}101102/**103* Set up the valid service provider categories and automatically104* register all available service providers.105*106* <p> The constructor is private in order to prevent creation of107* additional instances.108*/109private IIORegistry() {110super(initialCategories.iterator());111registerStandardSpis();112registerApplicationClasspathSpis();113}114115/**116* Returns the default {@code IIORegistry} instance used by117* the Image I/O API. This instance should be used for all118* registry functions.119*120* <p> Each {@code ThreadGroup} will receive its own121* instance; this allows different {@code Applet}s in the122* same browser (for example) to each have their own registry.123*124* @return the default registry for the current125* {@code ThreadGroup}.126*/127public static IIORegistry getDefaultInstance() {128AppContext context = AppContext.getAppContext();129IIORegistry registry =130(IIORegistry)context.get(IIORegistry.class);131if (registry == null) {132// Create an instance for this AppContext133registry = new IIORegistry();134context.put(IIORegistry.class, registry);135}136return registry;137}138139private void registerStandardSpis() {140// Hardwire standard SPIs141registerServiceProvider(new GIFImageReaderSpi());142registerServiceProvider(new GIFImageWriterSpi());143registerServiceProvider(new BMPImageReaderSpi());144registerServiceProvider(new BMPImageWriterSpi());145registerServiceProvider(new WBMPImageReaderSpi());146registerServiceProvider(new WBMPImageWriterSpi());147registerServiceProvider(new TIFFImageReaderSpi());148registerServiceProvider(new TIFFImageWriterSpi());149registerServiceProvider(new PNGImageReaderSpi());150registerServiceProvider(new PNGImageWriterSpi());151registerServiceProvider(new JPEGImageReaderSpi());152registerServiceProvider(new JPEGImageWriterSpi());153registerServiceProvider(new FileImageInputStreamSpi());154registerServiceProvider(new FileImageOutputStreamSpi());155registerServiceProvider(new InputStreamImageInputStreamSpi());156registerServiceProvider(new OutputStreamImageOutputStreamSpi());157registerServiceProvider(new RAFImageInputStreamSpi());158registerServiceProvider(new RAFImageOutputStreamSpi());159160registerInstalledProviders();161}162163/**164* Registers all available service providers found on the165* application class path, using the default166* {@code ClassLoader}. This method is typically invoked by167* the {@code ImageIO.scanForPlugins} method.168*169* @see javax.imageio.ImageIO#scanForPlugins170* @see ClassLoader#getResources171*/172@SuppressWarnings("removal")173public void registerApplicationClasspathSpis() {174// FIX: load only from application classpath175176ClassLoader loader = Thread.currentThread().getContextClassLoader();177178Iterator<Class<?>> categories = getCategories();179while (categories.hasNext()) {180@SuppressWarnings("unchecked")181Class<IIOServiceProvider> c = (Class<IIOServiceProvider>)categories.next();182Iterator<IIOServiceProvider> riter =183ServiceLoader.load(c, loader).iterator();184while (riter.hasNext()) {185try {186// Note that the next() call is required to be inside187// the try/catch block; see 6342404.188IIOServiceProvider r = riter.next();189registerServiceProvider(r);190} catch (ServiceConfigurationError err) {191if (System.getSecurityManager() != null) {192// In the applet case, we will catch the error so193// registration of other plugins can proceed194err.printStackTrace();195} else {196// In the application case, we will throw the197// error to indicate app/system misconfiguration198throw err;199}200}201}202}203}204205@SuppressWarnings("removal")206private void registerInstalledProviders() {207/*208We need to load installed providers209in the privileged mode in order to210be able read corresponding jar files even if211file read capability is restricted (like the212applet context case).213*/214PrivilegedAction<Object> doRegistration =215new PrivilegedAction<Object>() {216public Object run() {217Iterator<Class<?>> categories = getCategories();218while (categories.hasNext()) {219@SuppressWarnings("unchecked")220Class<IIOServiceProvider> c = (Class<IIOServiceProvider>)categories.next();221for (IIOServiceProvider p : ServiceLoader.loadInstalled(c)) {222registerServiceProvider(p);223}224}225return this;226}227};228229AccessController.doPrivileged(doRegistration);230}231}232233234