/* * ImageI/O-Ext - OpenSource Java Image translation Library * http://www.geo-solutions.it/ * http://java.net/projects/imageio-ext/ * (C) 2007 - 2009, GeoSolutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * either version 3 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ package it.geosolutions.imageio.stream.input.spi; import it.geosolutions.imageio.stream.eraf.EnhancedRandomAccessFile; import it.geosolutions.imageio.stream.input.FileImageInputStreamExtFileChannelImpl; import it.geosolutions.imageio.stream.input.FileImageInputStreamExtImpl; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.channels.FileChannel; import java.util.Iterator; import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.imageio.spi.ImageInputStreamSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.stream.ImageInputStream; import com.sun.imageio.spi.FileImageInputStreamSpi; import com.sun.media.imageio.stream.FileChannelImageInputStream; /** * Implementation of an {@link ImageInputStreamSpi} for instantiating an * {@link ImageInputStream} capable of connecting to a {@link File} by means of * an {@link EnhancedRandomAccessFile} which gives buffering capabilities. * * <p> * It is worth to point out that {@link ImageIO} already provide the * {@link FileChannelImageInputStream} in order to efficiently access images * with buffering. despite to this I have ran into many problems with * {@link FileChannel}s especially on Windows machines, hence I came up with * this {@link ImageInputStream} subclass and this {@link ImageInputStreamSpi} * which gives similar performances for most uses but far less problems. * * * @see ImageInputStream * @see ImageInputStreamSpi * @see ImageIO#createImageInputStream(Object) * * @author Daniele Romagnoli, GeoSolutions * @author Simone Giannecchini, GeoSolutions */ public class FileImageInputStreamExtImplSpi extends ImageInputStreamSpi { /** Logger. */ private final static Logger LOGGER = Logger .getLogger("it.geosolutions.imageio.stream.input.spi"); private static final String vendorName = "GeoSolutions"; private static final String version = "1.0"; private static final Class<File> inputClass = File.class; private static volatile boolean useFileChannel; static { useFileChannel = Boolean.getBoolean("it.geosolutions.stream.useFileChannel"); if (useFileChannel && LOGGER.isLoggable(Level.INFO)) { LOGGER.info("The FileImageInputStreamExtImplSpi will use File channels instead of " + "Enhanced Random Access Files"); } } /** * Constructs a blank {@link ImageInputStreamSpi}. It is up to the subclass * to initialize instance variables and/or override method implementations * in order to provide working versions of all methods. * */ public FileImageInputStreamExtImplSpi() { super(vendorName, version, inputClass); } /** * @see ImageInputStreamSpi#getDescription(Locale). */ public String getDescription(Locale locale) { return "Service provider that wraps a FileImageInputStream"; } /** * Upon registration, this method ensures that this SPI is listed at the top * of the ImageInputStreamSpi items, so that it will be invoked before the * default FileImageInputStreamSpi * * @param registry * ServiceRegistry where this object has been registered. * @param category * a Class object indicating the registry category under which * this object has been registered. */ public void onRegistration(ServiceRegistry registry, Class<?> category) { super.onRegistration(registry, category); Class<ImageInputStreamSpi> targetClass = ImageInputStreamSpi.class; for (Iterator<? extends ImageInputStreamSpi> i = registry.getServiceProviders(targetClass, true); i.hasNext();) { ImageInputStreamSpi other = i.next(); if (other instanceof FileImageInputStreamSpi) registry.deregisterServiceProvider(other); if (this != other) registry.setOrdering(targetClass, this, other); } } /** * Returns an instance of the ImageInputStream implementation associated * with this service provider. * * @param input * an object of the class type returned by getInputClass. * @param useCache * a boolean indicating whether a cache eraf should be used, in * cases where it is optional. * * @param cacheDir * a File indicating where the cache eraf should be created, or * null to use the system directory. * * * @return an ImageInputStream instance. * * @throws IllegalArgumentException * if input is not an instance of the correct class or is null. */ public ImageInputStream createInputStreamInstance(Object input, boolean useCache, File cacheDir) { if (!(input instanceof File)) { if (LOGGER.isLoggable(Level.FINE)) LOGGER.fine("THe provided input is not a eraf."); return null; } try { return new FileImageInputStreamExtImpl((File) input); } catch (FileNotFoundException e) { if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, e.getLocalizedMessage(), e); return null; } catch (IOException e) { if (LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, e.getLocalizedMessage(), e); return null; } } public static boolean isUseFileChannel() { return useFileChannel; } public static void setUseFileChannel(boolean useFileChannel) { FileImageInputStreamExtImplSpi.useFileChannel = useFileChannel; } }