1 /*
   2  * Copyright (c) 2000, 2007, 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.stream;
  27 
  28 import java.io.File;
  29 import java.io.FileNotFoundException;
  30 import java.io.IOException;
  31 import java.io.RandomAccessFile;
  32 import com.sun.imageio.stream.CloseableDisposerRecord;
  33 import com.sun.imageio.stream.StreamFinalizer;
  34 import sun.java2d.Disposer;
  35 
  36 /**
  37  * An implementation of {@code ImageInputStream} that gets its
  38  * input from a {@code File} or {@code RandomAccessFile}.
  39  * The file contents are assumed to be stable during the lifetime of
  40  * the object.
  41  *
  42  */
  43 public class FileImageInputStream extends ImageInputStreamImpl {
  44 
  45     private RandomAccessFile raf;
  46 
  47     /** The referent to be registered with the Disposer. */
  48     private final Object disposerReferent;
  49 
  50     /** The DisposerRecord that closes the underlying RandomAccessFile. */
  51     private final CloseableDisposerRecord disposerRecord;
  52 
  53     /**
  54      * Constructs a {@code FileImageInputStream} that will read
  55      * from a given {@code File}.
  56      *
  57      * <p> The file contents must not change between the time this
  58      * object is constructed and the time of the last call to a read
  59      * method.
  60      *
  61      * @param f a {@code File} to read from.
  62      *
  63      * @exception IllegalArgumentException if {@code f} is
  64      * {@code null}.
  65      * @exception SecurityException if a security manager exists
  66      * and does not allow read access to the file.
  67      * @exception FileNotFoundException if {@code f} is a
  68      * directory or cannot be opened for reading for any other reason.
  69      * @exception IOException if an I/O error occurs.
  70      */
  71     public FileImageInputStream(File f)
  72         throws FileNotFoundException, IOException {
  73         this(f == null ? null : new RandomAccessFile(f, "r"));
  74     }
  75 
  76     /**
  77      * Constructs a {@code FileImageInputStream} that will read
  78      * from a given {@code RandomAccessFile}.
  79      *
  80      * <p> The file contents must not change between the time this
  81      * object is constructed and the time of the last call to a read
  82      * method.
  83      *
  84      * @param raf a {@code RandomAccessFile} to read from.
  85      *
  86      * @exception IllegalArgumentException if {@code raf} is
  87      * {@code null}.
  88      */
  89     public FileImageInputStream(RandomAccessFile raf) {
  90         if (raf == null) {
  91             throw new IllegalArgumentException("raf == null!");
  92         }
  93         this.raf = raf;
  94 
  95         disposerRecord = new CloseableDisposerRecord(raf);
  96         if (getClass() == FileImageInputStream.class) {
  97             disposerReferent = new Object();
  98             Disposer.addRecord(disposerReferent, disposerRecord);
  99         } else {
 100             disposerReferent = new StreamFinalizer(this);
 101         }
 102     }
 103 
 104     public int read() throws IOException {
 105         checkClosed();
 106         bitOffset = 0;
 107         int val = raf.read();
 108         if (val != -1) {
 109             ++streamPos;
 110         }
 111         return val;
 112     }
 113 
 114     public int read(byte[] b, int off, int len) throws IOException {
 115         checkClosed();
 116         bitOffset = 0;
 117         int nbytes = raf.read(b, off, len);
 118         if (nbytes != -1) {
 119             streamPos += nbytes;
 120         }
 121         return nbytes;
 122     }
 123 
 124     /**
 125      * Returns the length of the underlying file, or {@code -1}
 126      * if it is unknown.
 127      *
 128      * @return the file length as a {@code long}, or
 129      * {@code -1}.
 130      */
 131     public long length() {
 132         try {
 133             checkClosed();
 134             return raf.length();
 135         } catch (IOException e) {
 136             return -1L;
 137         }
 138     }
 139 
 140     public void seek(long pos) throws IOException {
 141         checkClosed();
 142         if (pos < flushedPos) {
 143             throw new IndexOutOfBoundsException("pos < flushedPos!");
 144         }
 145         bitOffset = 0;
 146         raf.seek(pos);
 147         streamPos = raf.getFilePointer();
 148     }
 149 
 150     public void close() throws IOException {
 151         super.close();
 152         disposerRecord.dispose(); // this closes the RandomAccessFile
 153         raf = null;
 154     }
 155 
 156     /**
 157      * {@inheritDoc}
 158      */
 159     protected void finalize() throws Throwable {
 160         // Empty finalizer: for performance reasons we instead use the
 161         // Disposer mechanism for ensuring that the underlying
 162         // RandomAccessFile is closed prior to garbage collection
 163     }
 164 }
--- EOF ---