001
014
015 package com.liferay.portal.kernel.util;
016
017 import java.io.File;
018 import java.io.IOException;
019 import java.io.InputStream;
020 import java.io.RandomAccessFile;
021
022
028 public class RandomAccessInputStream extends InputStream {
029
030 public RandomAccessInputStream(InputStream inputStream) throws IOException {
031 _inputStream = inputStream;
032
033 _file = FileUtil.createTempFile();
034
035 _randomAccessFileCache = new RandomAccessFile(_file, "rw");
036 }
037
038 @Override
039 public void close() throws IOException {
040 super.close();
041
042 _randomAccessFileCache.close();
043
044 FileUtil.delete(_file);
045 }
046
047 @Override
048 public synchronized void mark(int readLimit) {
049 _markPosition = _pointer;
050 }
051
052 @Override
053 public boolean markSupported() {
054 return true;
055 }
056
057 @Override
058 public int read() throws IOException {
059 long next = _pointer + 1;
060
061 long position = readUntil(next);
062
063 if (position >= next) {
064 _randomAccessFileCache.seek(_pointer++);
065
066 return _randomAccessFileCache.read();
067 }
068 else {
069 return -1;
070 }
071 }
072
073 @Override
074 public int read(byte[] bytes, int offset, int length) throws IOException {
075 if (bytes == null) {
076 throw new NullPointerException();
077 }
078
079 if ((offset < 0) || (length < 0) || (offset + length > bytes.length)) {
080 throw new IndexOutOfBoundsException();
081 }
082
083 if (length == 0) {
084 return 0;
085 }
086
087 long position = readUntil(_pointer + length);
088
089 length = (int)Math.min(length, position - _pointer);
090
091 if (length > 0) {
092 _randomAccessFileCache.seek(_pointer);
093
094 _randomAccessFileCache.readFully(bytes, offset, length);
095
096 _pointer += length;
097
098 return length;
099 }
100 else {
101 return -1;
102 }
103 }
104
105 @Override
106 public synchronized void reset() throws IOException {
107 if (_markPosition != -1) {
108 seek(_markPosition);
109 }
110 }
111
112 public void seek(long position) throws IOException {
113 if (position < 0) {
114 throw new IOException("Error while seeking stream");
115 }
116
117 _pointer = position;
118 }
119
120 @Override
121 protected void finalize() throws Throwable {
122 super.finalize();
123
124 close();
125 }
126
127 protected long readUntil(long position) throws IOException {
128 if (position < _length) {
129 return position;
130 }
131
132 if (_foundEOF) {
133 return _length;
134 }
135
136 long lengthToRead = position - _length;
137
138 _randomAccessFileCache.seek(_length);
139
140 byte[] buffer = new byte[1024];
141
142 while (lengthToRead > 0) {
143 int bytesRead = _inputStream.read(
144 buffer, 0, (int) Math.min(lengthToRead, buffer.length));
145
146 if (bytesRead == -1) {
147 _foundEOF = true;
148
149 return _length;
150 }
151
152 _randomAccessFileCache.setLength(
153 _randomAccessFileCache.length() + bytesRead);
154
155 _randomAccessFileCache.write(buffer, 0, bytesRead);
156
157 lengthToRead -= bytesRead;
158
159 _length += bytesRead;
160 }
161
162 return position;
163 }
164
165 private File _file;
166 private boolean _foundEOF;
167 private InputStream _inputStream;
168 private long _length;
169 private long _markPosition = -1;
170 private long _pointer;
171 private RandomAccessFile _randomAccessFileCache;
172
173 }