Path: blob/master/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java
41153 views
/*1* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.imageio.stream;2627import java.io.InputStream;28import java.io.IOException;29import com.sun.imageio.stream.StreamFinalizer;30import sun.java2d.Disposer;31import sun.java2d.DisposerRecord;3233/**34* An implementation of {@code ImageInputStream} that gets its35* input from a regular {@code InputStream}. A memory buffer is36* used to cache at least the data between the discard position and37* the current read position.38*39* <p> In general, it is preferable to use a40* {@code FileCacheImageInputStream} when reading from a regular41* {@code InputStream}. This class is provided for cases where42* it is not possible to create a writable temporary file.43*44*/45public class MemoryCacheImageInputStream extends ImageInputStreamImpl {4647private InputStream stream;4849private MemoryCache cache = new MemoryCache();5051/** The referent to be registered with the Disposer. */52private final Object disposerReferent;5354/** The DisposerRecord that resets the underlying MemoryCache. */55private final DisposerRecord disposerRecord;5657/**58* Constructs a {@code MemoryCacheImageInputStream} that will read59* from a given {@code InputStream}.60*61* @param stream an {@code InputStream} to read from.62*63* @exception IllegalArgumentException if {@code stream} is64* {@code null}.65*/66public MemoryCacheImageInputStream(InputStream stream) {67if (stream == null) {68throw new IllegalArgumentException("stream == null!");69}70this.stream = stream;7172disposerRecord = new StreamDisposerRecord(cache);73if (getClass() == MemoryCacheImageInputStream.class) {74disposerReferent = new Object();75Disposer.addRecord(disposerReferent, disposerRecord);76} else {77disposerReferent = new StreamFinalizer(this);78}79}8081public int read() throws IOException {82checkClosed();83bitOffset = 0;84long pos = cache.loadFromStream(stream, streamPos+1);85if (pos >= streamPos+1) {86return cache.read(streamPos++);87} else {88return -1;89}90}9192public int read(byte[] b, int off, int len) throws IOException {93checkClosed();9495if (b == null) {96throw new NullPointerException("b == null!");97}98if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {99throw new IndexOutOfBoundsException100("off < 0 || len < 0 || off+len > b.length || off+len < 0!");101}102103bitOffset = 0;104105if (len == 0) {106return 0;107}108109long pos = cache.loadFromStream(stream, streamPos+len);110111len = (int)(pos - streamPos); // In case stream ended early112113if (len > 0) {114cache.read(b, off, len, streamPos);115streamPos += len;116return len;117} else {118return -1;119}120}121122public void flushBefore(long pos) throws IOException {123super.flushBefore(pos); // this will call checkClosed() for us124cache.disposeBefore(pos);125}126127/**128* Returns {@code true} since this129* {@code ImageInputStream} caches data in order to allow130* seeking backwards.131*132* @return {@code true}.133*134* @see #isCachedMemory135* @see #isCachedFile136*/137public boolean isCached() {138return true;139}140141/**142* Returns {@code false} since this143* {@code ImageInputStream} does not maintain a file cache.144*145* @return {@code false}.146*147* @see #isCached148* @see #isCachedMemory149*/150public boolean isCachedFile() {151return false;152}153154/**155* Returns {@code true} since this156* {@code ImageInputStream} maintains a main memory cache.157*158* @return {@code true}.159*160* @see #isCached161* @see #isCachedFile162*/163public boolean isCachedMemory() {164return true;165}166167/**168* Closes this {@code MemoryCacheImageInputStream}, freeing169* the cache. The source {@code InputStream} is not closed.170*/171public void close() throws IOException {172super.close();173disposerRecord.dispose(); // this resets the MemoryCache174stream = null;175cache = null;176}177178/**179* {@inheritDoc}180*181* @deprecated The {@code finalize} method has been deprecated.182* Subclasses that override {@code finalize} in order to perform cleanup183* should be modified to use alternative cleanup mechanisms and184* to remove the overriding {@code finalize} method.185* When overriding the {@code finalize} method, its implementation must explicitly186* ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.187* See the specification for {@link Object#finalize()} for further188* information about migration options.189*/190@Deprecated(since="9")191protected void finalize() throws Throwable {192// Empty finalizer: for performance reasons we instead use the193// Disposer mechanism for ensuring that the underlying194// MemoryCache is reset prior to garbage collection195}196197private static class StreamDisposerRecord implements DisposerRecord {198private MemoryCache cache;199200public StreamDisposerRecord(MemoryCache cache) {201this.cache = cache;202}203204public synchronized void dispose() {205if (cache != null) {206cache.reset();207cache = null;208}209}210}211}212213214