Save This Page
Home » openjdk-7 » javax » imageio » stream » [javadoc | source]
    1   /*
    2    * Copyright 2000-2007 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.imageio.stream;
   27   
   28   import java.io.InputStream;
   29   import java.io.IOException;
   30   import com.sun.imageio.stream.StreamFinalizer;
   31   import sun.java2d.Disposer;
   32   import sun.java2d.DisposerRecord;
   33   
   34   /**
   35    * An implementation of <code>ImageInputStream</code> that gets its
   36    * input from a regular <code>InputStream</code>.  A memory buffer is
   37    * used to cache at least the data between the discard position and
   38    * the current read position.
   39    *
   40    * <p> In general, it is preferable to use a
   41    * <code>FileCacheImageInputStream</code> when reading from a regular
   42    * <code>InputStream</code>.  This class is provided for cases where
   43    * it is not possible to create a writable temporary file.
   44    *
   45    */
   46   public class MemoryCacheImageInputStream extends ImageInputStreamImpl {
   47   
   48       private InputStream stream;
   49   
   50       private MemoryCache cache = new MemoryCache();
   51   
   52       /** The referent to be registered with the Disposer. */
   53       private final Object disposerReferent;
   54   
   55       /** The DisposerRecord that resets the underlying MemoryCache. */
   56       private final DisposerRecord disposerRecord;
   57   
   58       /**
   59        * Constructs a <code>MemoryCacheImageInputStream</code> that will read
   60        * from a given <code>InputStream</code>.
   61        *
   62        * @param stream an <code>InputStream</code> to read from.
   63        *
   64        * @exception IllegalArgumentException if <code>stream</code> is
   65        * <code>null</code>.
   66        */
   67       public MemoryCacheImageInputStream(InputStream stream) {
   68           if (stream == null) {
   69               throw new IllegalArgumentException("stream == null!");
   70           }
   71           this.stream = stream;
   72   
   73           disposerRecord = new StreamDisposerRecord(cache);
   74           if (getClass() == MemoryCacheImageInputStream.class) {
   75               disposerReferent = new Object();
   76               Disposer.addRecord(disposerReferent, disposerRecord);
   77           } else {
   78               disposerReferent = new StreamFinalizer(this);
   79           }
   80       }
   81   
   82       public int read() throws IOException {
   83           checkClosed();
   84           bitOffset = 0;
   85           long pos = cache.loadFromStream(stream, streamPos+1);
   86           if (pos >= streamPos+1) {
   87               return cache.read(streamPos++);
   88           } else {
   89               return -1;
   90           }
   91       }
   92   
   93       public int read(byte[] b, int off, int len) throws IOException {
   94           checkClosed();
   95   
   96           if (b == null) {
   97               throw new NullPointerException("b == null!");
   98           }
   99           if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {
  100               throw new IndexOutOfBoundsException
  101                   ("off < 0 || len < 0 || off+len > b.length || off+len < 0!");
  102           }
  103   
  104           bitOffset = 0;
  105   
  106           if (len == 0) {
  107               return 0;
  108           }
  109   
  110           long pos = cache.loadFromStream(stream, streamPos+len);
  111   
  112           len = (int)(pos - streamPos);  // In case stream ended early
  113   
  114           if (len > 0) {
  115               cache.read(b, off, len, streamPos);
  116               streamPos += len;
  117               return len;
  118           } else {
  119               return -1;
  120           }
  121       }
  122   
  123       public void flushBefore(long pos) throws IOException {
  124           super.flushBefore(pos); // this will call checkClosed() for us
  125           cache.disposeBefore(pos);
  126       }
  127   
  128       /**
  129        * Returns <code>true</code> since this
  130        * <code>ImageInputStream</code> caches data in order to allow
  131        * seeking backwards.
  132        *
  133        * @return <code>true</code>.
  134        *
  135        * @see #isCachedMemory
  136        * @see #isCachedFile
  137        */
  138       public boolean isCached() {
  139           return true;
  140       }
  141   
  142       /**
  143        * Returns <code>false</code> since this
  144        * <code>ImageInputStream</code> does not maintain a file cache.
  145        *
  146        * @return <code>false</code>.
  147        *
  148        * @see #isCached
  149        * @see #isCachedMemory
  150        */
  151       public boolean isCachedFile() {
  152           return false;
  153       }
  154   
  155       /**
  156        * Returns <code>true</code> since this
  157        * <code>ImageInputStream</code> maintains a main memory cache.
  158        *
  159        * @return <code>true</code>.
  160        *
  161        * @see #isCached
  162        * @see #isCachedFile
  163        */
  164       public boolean isCachedMemory() {
  165           return true;
  166       }
  167   
  168       /**
  169        * Closes this <code>MemoryCacheImageInputStream</code>, freeing
  170        * the cache.  The source <code>InputStream</code> is not closed.
  171        */
  172       public void close() throws IOException {
  173           super.close();
  174           disposerRecord.dispose(); // this resets the MemoryCache
  175           stream = null;
  176           cache = null;
  177       }
  178   
  179       /**
  180        * {@inheritDoc}
  181        */
  182       protected void finalize() throws Throwable {
  183           // Empty finalizer: for performance reasons we instead use the
  184           // Disposer mechanism for ensuring that the underlying
  185           // MemoryCache is reset prior to garbage collection
  186       }
  187   
  188       private static class StreamDisposerRecord implements DisposerRecord {
  189           private MemoryCache cache;
  190   
  191           public StreamDisposerRecord(MemoryCache cache) {
  192               this.cache = cache;
  193           }
  194   
  195           public synchronized void dispose() {
  196               if (cache != null) {
  197                   cache.reset();
  198                   cache = null;
  199               }
  200           }
  201       }
  202   }

Save This Page
Home » openjdk-7 » javax » imageio » stream » [javadoc | source]