1. /*
  2. * @(#)MemoryCacheImageInputStream.java 1.22 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.imageio.stream;
  8. import java.io.InputStream;
  9. import java.io.IOException;
  10. import java.io.RandomAccessFile;
  11. import java.util.ArrayList;
  12. /**
  13. * An implementation of <code>ImageInputStream</code> that gets its
  14. * input from a regular <code>InputStream</code>. A memory buffer is
  15. * used to cache at least the data between the discard position and
  16. * the current read position.
  17. *
  18. * <p> In general, it is preferable to use a
  19. * <code>FileCacheImageInputStream</code> when reading from a regular
  20. * <code>InputStream</code>. This class is provided for cases where
  21. * it is not possible to create a writable temporary file.
  22. *
  23. * @version 0.5
  24. */
  25. public class MemoryCacheImageInputStream extends ImageInputStreamImpl {
  26. private InputStream stream;
  27. private MemoryCache cache = new MemoryCache();
  28. /**
  29. * Constructs a <code>MemoryCacheImageInputStream</code> that will read
  30. * from a given <code>InputStream</code>.
  31. *
  32. * @param stream an <code>InputStream</code> to read from.
  33. *
  34. * @exception IllegalArgumentException if <code>stream</code> is
  35. * <code>null</code>.
  36. */
  37. public MemoryCacheImageInputStream(InputStream stream) {
  38. if (stream == null) {
  39. throw new IllegalArgumentException("stream == null!");
  40. }
  41. this.stream = stream;
  42. }
  43. public int read() throws IOException {
  44. checkClosed();
  45. bitOffset = 0;
  46. long thisByte = streamPos;
  47. long pos = cache.loadFromStream(stream, streamPos+1);
  48. if (pos >= streamPos+1) {
  49. return cache.read(streamPos++);
  50. } else {
  51. return -1;
  52. }
  53. }
  54. public int read(byte[] b, int off, int len) throws IOException {
  55. checkClosed();
  56. // Will throw NullPointerException
  57. if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {
  58. throw new IndexOutOfBoundsException
  59. ("off < 0 || len < 0 || off + len > b.length!");
  60. }
  61. bitOffset = 0;
  62. if (len == 0) {
  63. return 0;
  64. }
  65. long pos = cache.loadFromStream(stream, streamPos+len);
  66. len = (int)(pos - streamPos); // In case stream ended early
  67. if (len > 0) {
  68. cache.read(b, off, len, streamPos);
  69. streamPos += len;
  70. return len;
  71. } else {
  72. return -1;
  73. }
  74. }
  75. public void flushBefore(long pos) throws IOException {
  76. super.flushBefore(pos);
  77. cache.disposeBefore(pos);
  78. }
  79. /**
  80. * Returns <code>true</code> since this
  81. * <code>ImageInputStream</code> caches data in order to allow
  82. * seeking backwards.
  83. *
  84. * @return <code>true</code>.
  85. *
  86. * @see #isCachedMemory
  87. * @see #isCachedFile
  88. */
  89. public boolean isCached() {
  90. return true;
  91. }
  92. /**
  93. * Returns <code>false</code> since this
  94. * <code>ImageInputStream</code> does not maintain a file cache.
  95. *
  96. * @return <code>false</code>.
  97. *
  98. * @see #isCached
  99. * @see #isCachedMemory
  100. */
  101. public boolean isCachedFile() {
  102. return false;
  103. }
  104. /**
  105. * Returns <code>true</code> since this
  106. * <code>ImageInputStream</code> maintains a main memory cache.
  107. *
  108. * @return <code>true</code>.
  109. *
  110. * @see #isCached
  111. * @see #isCachedFile
  112. */
  113. public boolean isCachedMemory() {
  114. return true;
  115. }
  116. /**
  117. * Closes this <code>MemoryCacheImageInputStream</code>, freeing
  118. * the cache. The source <code>InputStream</code> is not closed.
  119. */
  120. public void close() throws IOException {
  121. super.close();
  122. cache.reset();
  123. stream = null;
  124. }
  125. }