![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.aries.util.io.RememberingInputStream Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIESOR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.aries.util.io;
import java.io.IOException;
import java.io.InputStream;
import org.apache.aries.util.internal.MessageUtil;
/**
* This class can be used to buffer an arbitrary amount of content from an input stream and be able to reset to
* the start.
*/
public class RememberingInputStream extends InputStream {
/** The size by which to grow our array */
private static final int bufferGrowthSize = 0x4000;
/** The bytes that have been read so far */
private byte[] bytes = new byte[bufferGrowthSize];
/** Index of the next empty entry in the array */
private int pos = 0;
/** The input stream that actually holds the data */
private final InputStream stream;
/** Index of the last valid byte in the byte array */
private int maxRead = -1;
/** The point to reset to */
private int markPoint = -1;
public RememberingInputStream(InputStream in) throws IOException{
stream = in;
// Pre fill with data that we know we're going to need - it's
// more efficient than the single byte reads are - hopefully
// someone reading a lot of data will do reads in bulk
maxRead = stream.read(bytes) - 1;
}
@Override
public int read() throws IOException {
if(pos <= maxRead)
{
//We can't return the byte directly, because it is signed
//We can pretend this is an unsigned byte by using boolean
//& to set the low end byte of an int.
return bytes[pos++] & 0xFF;
} else {
int i = stream.read();
if(i<0)
return i;
ensureCapacity(0);
bytes[pos++] = (byte) i;
return i;
}
}
/**
* Ensure our internal byte array can hold enough data
* @param i one less than the number of bytes that need
* to be held.
*/
private void ensureCapacity(int i) {
if((pos + i) >= bytes.length) {
byte[] tmp = bytes;
int newLength = bytes.length + bufferGrowthSize;
while(newLength < pos + i) {
newLength += bufferGrowthSize;
}
bytes = new byte[newLength];
System.arraycopy(tmp, 0, bytes, 0, (maxRead >= pos) ? maxRead + 1 : pos);
}
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if(pos <= maxRead) {
if(pos + len <= maxRead)
{
System.arraycopy(bytes, pos, b, off, len);
pos += len;
return len;
} else {
int lengthLeftOfBuffer = (maxRead - pos) + 1;
System.arraycopy(bytes, pos, b, off, lengthLeftOfBuffer);
int read = stream.read(b, off + lengthLeftOfBuffer, len - lengthLeftOfBuffer);
if(read < 0) {
pos += lengthLeftOfBuffer;
return lengthLeftOfBuffer;
}
ensureCapacity(lengthLeftOfBuffer + read - 1);
System.arraycopy(b, off + lengthLeftOfBuffer, bytes, maxRead + 1, read);
pos += (lengthLeftOfBuffer + read);
return lengthLeftOfBuffer + read;
}
} else {
int i = stream.read(b, off, len);
if(i<0)
return i;
ensureCapacity(i - 1);
System.arraycopy(b, off, bytes, pos, i);
pos += i;
return i;
}
}
@Override
public long skip(long n) throws IOException {
throw new IOException(MessageUtil.getMessage("UTIL0017E"));
}
@Override
public int available() throws IOException {
if(pos <= maxRead)
return (maxRead - pos) + 1;
else
return stream.available();
}
@Override
public synchronized void mark(int readlimit) {
markPoint = pos;
}
@Override
public synchronized void reset() throws IOException {
if(maxRead < pos)
maxRead = pos - 1;
pos = markPoint;
}
@Override
public boolean markSupported() {
return true;
}
/**
* Noop. Does not close the passed in archive, which is kept open for further reading.
*/
@Override
public void close() throws IOException {
//No op, don't close the parent.
}
/**
* Actually closes the underlying InputStream. Call this method instead of close, which is implemented as a no-op.
* Alternatively call close directly on the parent.
* @throws IOException
*/
public void closeUnderlying() throws IOException {
stream.close();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy