/*
* 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;
import it.geosolutions.imageio.stream.eraf.EnhancedRandomAccessFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageInputStreamImpl;
import com.sun.media.imageio.stream.FileChannelImageInputStream;
/**
* An implementation of {@link ImageInputStream} that gets its input from a
* {@link File} dealing with FileChannels.
*
* @author Simone Giannecchini, GeoSolutions SaS
* @author Daniele Romagnoli, GeoSolutions SaS
*/
public class FileImageInputStreamExtFileChannelImpl extends ImageInputStreamImpl
implements FileImageInputStreamExt {
/** the associated {@link File}*/
private File file;
/** the underlying {@link FileChannelImageInputStream} */
private FileChannelImageInputStream fileChannelInputStream;
public byte readByte() throws IOException {
return fileChannelInputStream.readByte();
}
public char readChar() throws IOException {
return fileChannelInputStream.readChar();
}
public double readDouble() throws IOException {
return fileChannelInputStream.readDouble();
}
public float readFloat() throws IOException {
return fileChannelInputStream.readFloat();
}
public void readFully(byte[] b, int off, int len) throws IOException {
fileChannelInputStream.readFully(b, off, len);
}
public void readFully(byte[] b) throws IOException {
fileChannelInputStream.readFully(b);
}
public int readInt() throws IOException {
return fileChannelInputStream.readInt();
}
public String readLine() throws IOException {
return fileChannelInputStream.readLine();
}
public ByteOrder getByteOrder() {
return fileChannelInputStream.getByteOrder();
}
public long getStreamPosition() throws IOException {
return fileChannelInputStream.getStreamPosition();
}
public int read(byte[] b) throws IOException {
return fileChannelInputStream.read(b);
}
public long skipBytes(long n) throws IOException {
return fileChannelInputStream.skipBytes(n);
}
public long readLong() throws IOException {
return fileChannelInputStream.readLong();
}
public short readShort() throws IOException {
return fileChannelInputStream.readShort();
}
public int readUnsignedByte() throws IOException {
return fileChannelInputStream.readUnsignedByte();
}
public long readUnsignedInt() throws IOException {
return fileChannelInputStream.readUnsignedInt();
}
public int readUnsignedShort() throws IOException {
return fileChannelInputStream.readUnsignedShort();
}
public String readUTF() throws IOException {
return fileChannelInputStream.readUTF();
}
public void setByteOrder(ByteOrder byteOrder) {
fileChannelInputStream.setByteOrder(byteOrder);
}
public int skipBytes(int n) throws IOException {
return fileChannelInputStream.skipBytes(n);
}
/**
* Constructs a {@link FileImageInputStreamExtFileChannelImpl} that will read from a
* given {@link File}.
*
* <p>
* The eraf contents must not change between the time this object is
* constructed and the time of the last call to a read method.
*
* @param f
* a {@link File} to read from.
*
* @exception NullPointerException
* if <code>f</code> is <code>null</code>.
* @exception SecurityException
* if a security manager exists and does not allow read
* access to the eraf.
* @exception FileNotFoundException
* if <code>f</code> is a directory or cannot be opened
* for reading for any other reason.
* @exception IOException
* if an I/O error occurs.
*/
public FileImageInputStreamExtFileChannelImpl(File f) throws FileNotFoundException,
IOException {
this(f, -1);
}
/**
* Constructs a {@link FileImageInputStreamExtFileChannelImpl} that will read from a
* given {@link File}.
*
* <p>
* The eraf contents must not change between the time this object is
* constructed and the time of the last call to a read method.
*
* @param f
* a {@link File} to read from.
* @param bufferSize
* size of the underlying buffer.
*
* @exception NullPointerException
* if <code>f</code> is <code>null</code>.
* @exception SecurityException
* if a security manager exists and does not allow read
* access to the eraf.
* @exception FileNotFoundException
* if <code>f</code> is a directory or cannot be opened
* for reading for any other reason.
* @exception IOException
* if an I/O error occurs.
*/
public FileImageInputStreamExtFileChannelImpl(File f, int bufferSize)
throws IOException {
// //
//
// Check that the input file is a valid file
//
// //
if (f == null) {
throw new NullPointerException("f == null!");
}
final StringBuilder buff = new StringBuilder("Invalid input file provided");
if (!f.exists() || f.isDirectory()) {
buff.append("exists: ").append(f.exists()).append("\n");
buff.append("isDirectory: ").append(f.isDirectory()).append("\n");
throw new FileNotFoundException(buff.toString());
}
if (!f.exists() || f.isDirectory() || !f.canRead()) {
buff.append("canRead: ").append(f.canRead()).append("\n");
throw new IOException(buff.toString());
}
this.file = f;
FileChannel fc = new FileInputStream(f).getChannel();
this.fileChannelInputStream = new FileChannelImageInputStream(fc);
// NOTE: this must be done accordingly to what ImageInputStreamImpl
// does, otherwise some ImageReader subclasses might not work.
this.fileChannelInputStream.setByteOrder(ByteOrder.BIG_ENDIAN);
}
/**
* Reads an int from the underlying {@link EnhancedRandomAccessFile}.
*/
public int read() throws IOException {
return fileChannelInputStream.read();
}
/**
* Read up to <code>len</code> bytes into an array, at a specified offset.
* This will block until at least one byte has been read.
*
* @param b
* the byte array to receive the bytes.
* @param off
* the offset in the array where copying will start.
* @param len
* the number of bytes to copy.
* @return the actual number of bytes read, or -1 if there is not more data
* due to the end of the eraf being reached.
*/
public int read(byte[] b, int off, int len) throws IOException {
return fileChannelInputStream.read(b, off, len);
}
/**
* Returns the length of the underlying eraf, or <code>-1</code> if it is
* unknown.
*
* @return the eraf length as a <code>long</code>, or <code>-1</code>.
*/
public long length() {
return fileChannelInputStream.length();
}
/**
* Seeks the current position to pos.
*/
public void seek(long pos) throws IOException {
fileChannelInputStream.seek(pos);
}
/**
* Closes the underlying {@link EnhancedRandomAccessFile}.
*
* @throws IOException
* in case something bad happens.
*/
public void close() throws IOException {
fileChannelInputStream.close();
}
/**
* Retrieves the {@link File} we are connected to.
*/
public File getFile() {
return file;
}
/**
* Disposes this {@link FileImageInputStreamExtFileChannelImpl} by closing its
* underlying {@link EnhancedRandomAccessFile}.
*
*/
public void dispose() {
try {
close();
} catch (IOException e) {
}
}
/**
* Provides a simple description for this {@link ImageInputStream}.
*
* @return a simple description for this {@link ImageInputStream}.
*/
public String toString() {
return "FileImageInputStreamExtFileChannelImpl which points to " + this.file.toString();
}
public File getTarget() {
return file;
}
public Class<File> getBinding() {
return File.class;
}
}