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) ||
080 ((offset + length) > bytes.length)) {
081
082 throw new IndexOutOfBoundsException();
083 }
084
085 if (length == 0) {
086 return 0;
087 }
088
089 long position = readUntil(_pointer + length);
090
091 length = (int)Math.min(length, position - _pointer);
092
093 if (length > 0) {
094 _randomAccessFileCache.seek(_pointer);
095
096 _randomAccessFileCache.readFully(bytes, offset, length);
097
098 _pointer += length;
099
100 return length;
101 }
102 else {
103 return -1;
104 }
105 }
106
107 @Override
108 public synchronized void reset() throws IOException {
109 if (_markPosition != -1) {
110 seek(_markPosition);
111 }
112 }
113
114 public void seek(long position) throws IOException {
115 if (position < 0) {
116 throw new IOException("Error while seeking stream");
117 }
118
119 _pointer = position;
120 }
121
122 @Override
123 protected void finalize() throws Throwable {
124 super.finalize();
125
126 close();
127 }
128
129 protected long readUntil(long position) throws IOException {
130 if (position < _length) {
131 return position;
132 }
133
134 if (_foundEOF) {
135 return _length;
136 }
137
138 long lengthToRead = position - _length;
139
140 _randomAccessFileCache.seek(_length);
141
142 byte[] buffer = new byte[1024];
143
144 while (lengthToRead > 0) {
145 int bytesRead = _inputStream.read(
146 buffer, 0, (int)Math.min(lengthToRead, buffer.length));
147
148 if (bytesRead == -1) {
149 _foundEOF = true;
150
151 return _length;
152 }
153
154 _randomAccessFileCache.setLength(
155 _randomAccessFileCache.length() + bytesRead);
156
157 _randomAccessFileCache.write(buffer, 0, bytesRead);
158
159 lengthToRead -= bytesRead;
160
161 _length += bytesRead;
162 }
163
164 return position;
165 }
166
167 private File _file;
168 private boolean _foundEOF;
169 private InputStream _inputStream;
170 private long _length;
171 private long _markPosition = -1;
172 private long _pointer;
173 private RandomAccessFile _randomAccessFileCache;
174
175 }