src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java

Print this page




  70     /**
  71      * Constructs a <code>FileCacheImageInputStream</code> that will read
  72      * from a given <code>InputStream</code>.
  73      *
  74      * <p> A temporary file is used as a cache.  If
  75      * <code>cacheDir</code>is non-<code>null</code> and is a
  76      * directory, the file will be created there.  If it is
  77      * <code>null</code>, the system-dependent default temporary-file
  78      * directory will be used (see the documentation for
  79      * <code>File.createTempFile</code> for details).
  80      *
  81      * @param stream an <code>InputStream</code> to read from.
  82      * @param cacheDir a <code>File</code> indicating where the
  83      * cache file should be created, or <code>null</code> to use the
  84      * system directory.
  85      *
  86      * @exception IllegalArgumentException if <code>stream</code> is
  87      * <code>null</code>.
  88      * @exception IllegalArgumentException if <code>cacheDir</code> is
  89      * non-<code>null</code> but is not a directory.
  90      * @exception IOException if a cache file cannot be created.
  91      */
  92     public FileCacheImageInputStream(InputStream stream, File cacheDir)
  93         throws IOException {
  94         if (stream == null) {
  95             throw new IllegalArgumentException("stream == null!");
  96         }
  97         if ((cacheDir != null) && !(cacheDir.isDirectory())) {
  98             throw new IllegalArgumentException("Not a directory!");
  99         }
 100         this.stream = stream;
 101         if (cacheDir == null)
 102             this.cacheFile = Files.createTempFile("imageio", ".tmp").toFile();
 103         else
 104             this.cacheFile = Files.createTempFile(cacheDir.toPath(), "imageio", ".tmp")
 105                                   .toFile();
 106         this.cache = new RandomAccessFile(cacheFile, "rw");
 107 
 108         this.closeAction = StreamCloser.createCloseAction(this);
 109         StreamCloser.addToQueue(closeAction);
 110 
 111         disposerRecord = new StreamDisposerRecord(cacheFile, cache);
 112         if (getClass() == FileCacheImageInputStream.class) {
 113             disposerReferent = new Object();
 114             Disposer.addRecord(disposerReferent, disposerRecord);
 115         } else {
 116             disposerReferent = new StreamFinalizer(this);
 117         }
 118     }
 119 
 120     /**
 121      * Ensures that at least <code>pos</code> bytes are cached,
 122      * or the end of the source is reached.  The return value
 123      * is equal to the smaller of <code>pos</code> and the
 124      * length of the source file.



 125      */
 126     private long readUntil(long pos) throws IOException {
 127         // We've already got enough data cached
 128         if (pos < length) {
 129             return pos;
 130         }
 131         // pos >= length but length isn't getting any bigger, so return it
 132         if (foundEOF) {
 133             return length;
 134         }
 135 
 136         long len = pos - length;
 137         cache.seek(length);
 138         while (len > 0) {
 139             // Copy a buffer's worth of data from the source to the cache
 140             // BUFFER_LENGTH will always fit into an int so this is safe
 141             int nbytes =
 142                 stream.read(buf, 0, (int)Math.min(len, (long)BUFFER_LENGTH));
 143             if (nbytes == -1) {
 144                 foundEOF = true;


 227 
 228     /**
 229      * Returns <code>false</code> since this
 230      * <code>ImageInputStream</code> does not maintain a main memory
 231      * cache.
 232      *
 233      * @return <code>false</code>.
 234      *
 235      * @see #isCached
 236      * @see #isCachedFile
 237      */
 238     public boolean isCachedMemory() {
 239         return false;
 240     }
 241 
 242     /**
 243      * Closes this <code>FileCacheImageInputStream</code>, closing
 244      * and removing the cache file.  The source <code>InputStream</code>
 245      * is not closed.
 246      *
 247      * @exception IOException if an error occurs.
 248      */
 249     public void close() throws IOException {
 250         super.close();
 251         disposerRecord.dispose(); // this will close/delete the cache file
 252         stream = null;
 253         cache = null;
 254         cacheFile = null;
 255         StreamCloser.removeFromQueue(closeAction);
 256     }
 257 
 258     /**
 259      * {@inheritDoc}
 260      */
 261     protected void finalize() throws Throwable {
 262         // Empty finalizer: for performance reasons we instead use the
 263         // Disposer mechanism for ensuring that the underlying
 264         // RandomAccessFile is closed/deleted prior to garbage collection
 265     }
 266 
 267     private static class StreamDisposerRecord implements DisposerRecord {




  70     /**
  71      * Constructs a <code>FileCacheImageInputStream</code> that will read
  72      * from a given <code>InputStream</code>.
  73      *
  74      * <p> A temporary file is used as a cache.  If
  75      * <code>cacheDir</code>is non-<code>null</code> and is a
  76      * directory, the file will be created there.  If it is
  77      * <code>null</code>, the system-dependent default temporary-file
  78      * directory will be used (see the documentation for
  79      * <code>File.createTempFile</code> for details).
  80      *
  81      * @param stream an <code>InputStream</code> to read from.
  82      * @param cacheDir a <code>File</code> indicating where the
  83      * cache file should be created, or <code>null</code> to use the
  84      * system directory.
  85      *
  86      * @exception IllegalArgumentException if <code>stream</code> is
  87      * <code>null</code>.
  88      * @exception IllegalArgumentException if <code>cacheDir</code> is
  89      * non-<code>null</code> but is not a directory.
  90      * @throws IOException if a cache file cannot be created.
  91      */
  92     public FileCacheImageInputStream(InputStream stream, File cacheDir)
  93         throws IOException {
  94         if (stream == null) {
  95             throw new IllegalArgumentException("stream == null!");
  96         }
  97         if ((cacheDir != null) && !(cacheDir.isDirectory())) {
  98             throw new IllegalArgumentException("Not a directory!");
  99         }
 100         this.stream = stream;
 101         if (cacheDir == null)
 102             this.cacheFile = Files.createTempFile("imageio", ".tmp").toFile();
 103         else
 104             this.cacheFile = Files.createTempFile(cacheDir.toPath(), "imageio", ".tmp")
 105                                   .toFile();
 106         this.cache = new RandomAccessFile(cacheFile, "rw");
 107 
 108         this.closeAction = StreamCloser.createCloseAction(this);
 109         StreamCloser.addToQueue(closeAction);
 110 
 111         disposerRecord = new StreamDisposerRecord(cacheFile, cache);
 112         if (getClass() == FileCacheImageInputStream.class) {
 113             disposerReferent = new Object();
 114             Disposer.addRecord(disposerReferent, disposerRecord);
 115         } else {
 116             disposerReferent = new StreamFinalizer(this);
 117         }
 118     }
 119 
 120     /**
 121      * Ensures that at least <code>pos</code> bytes are cached,
 122      * or the end of the source is reached.  The return value
 123      * is equal to the smaller of <code>pos</code> and the
 124      * length of the source file.
 125      * 
 126      * @throws IOException if an I/O error occurs while reading from the
 127      * source file
 128      */
 129     private long readUntil(long pos) throws IOException {
 130         // We've already got enough data cached
 131         if (pos < length) {
 132             return pos;
 133         }
 134         // pos >= length but length isn't getting any bigger, so return it
 135         if (foundEOF) {
 136             return length;
 137         }
 138 
 139         long len = pos - length;
 140         cache.seek(length);
 141         while (len > 0) {
 142             // Copy a buffer's worth of data from the source to the cache
 143             // BUFFER_LENGTH will always fit into an int so this is safe
 144             int nbytes =
 145                 stream.read(buf, 0, (int)Math.min(len, (long)BUFFER_LENGTH));
 146             if (nbytes == -1) {
 147                 foundEOF = true;


 230 
 231     /**
 232      * Returns <code>false</code> since this
 233      * <code>ImageInputStream</code> does not maintain a main memory
 234      * cache.
 235      *
 236      * @return <code>false</code>.
 237      *
 238      * @see #isCached
 239      * @see #isCachedFile
 240      */
 241     public boolean isCachedMemory() {
 242         return false;
 243     }
 244 
 245     /**
 246      * Closes this <code>FileCacheImageInputStream</code>, closing
 247      * and removing the cache file.  The source <code>InputStream</code>
 248      * is not closed.
 249      *
 250      * @throws IOException if an error occurs.
 251      */
 252     public void close() throws IOException {
 253         super.close();
 254         disposerRecord.dispose(); // this will close/delete the cache file
 255         stream = null;
 256         cache = null;
 257         cacheFile = null;
 258         StreamCloser.removeFromQueue(closeAction);
 259     }
 260 
 261     /**
 262      * {@inheritDoc}
 263      */
 264     protected void finalize() throws Throwable {
 265         // Empty finalizer: for performance reasons we instead use the
 266         // Disposer mechanism for ensuring that the underlying
 267         // RandomAccessFile is closed/deleted prior to garbage collection
 268     }
 269 
 270     private static class StreamDisposerRecord implements DisposerRecord {