org.apache.xml.security.utils.UnsyncByteArrayInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xmlsec Show documentation
Show all versions of xmlsec Show documentation
Apache XML Security for Java supports XML-Signature Syntax and Processing,
W3C Recommendation 12 February 2002, and XML Encryption Syntax and
Processing, W3C Recommendation 10 December 2002. As of version 1.4,
the library supports the standard Java API JSR-105: XML Digital Signature APIs.
/*
* 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 WARRANTIES OR 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.xml.security.utils;
import java.io.IOException;
import java.io.InputStream;
/**
* A specialized {@link InputStream } for reading the contents of a byte array.
*
* @see UnsyncByteArrayOutputStream
*/
public class UnsyncByteArrayInputStream extends InputStream {
/**
* The {@code byte} array containing the bytes to stream over.
*/
protected byte[] buf;
/**
* The current position within the byte array.
*/
protected int pos;
/**
* The current mark position. Initially set to 0 or the offset
* parameter within the constructor.
*/
protected int mark;
/**
* The total number of bytes initially available in the byte array
* {@code buf}.
*/
protected int count;
/**
* Constructs a new {@code ByteArrayInputStream} on the byte array
* {@code buf}.
*
* @param buf
* the byte array to stream over.
*/
public UnsyncByteArrayInputStream(byte[] buf) {
this(buf, 0, buf.length);
}
/**
* Constructs a new {@code ByteArrayInputStream} on the byte array
* {@code buf} with the initial position set to {@code offset} and the
* number of bytes available set to {@code offset} + {@code length}.
*
* @param buf
* the byte array to stream over.
* @param offset
* the initial position in {@code buf} to start streaming from.
* @param length
* the number of bytes available for streaming.
*/
public UnsyncByteArrayInputStream(byte[] buf, int offset, int length) {
this.buf = buf;
pos = offset;
mark = offset;
count = offset + length > buf.length ? buf.length : offset + length;
}
/**
* Returns the number of bytes that are available before this stream will
* block. This method returns the number of bytes yet to be read from the
* source byte array.
*
* @return the number of bytes available before blocking.
*/
@Override
public int available() {
return count - pos;
}
/**
* Closes this stream and frees resources associated with this stream.
*
* @throws IOException
* if an I/O error occurs while closing this stream.
*/
@Override
public void close() throws IOException {
// Do nothing on close, this matches JDK behaviour.
}
/**
* Sets a mark position in this ByteArrayInputStream. The parameter
* {@code readlimit} is ignored. Sending {@code reset()} will reposition the
* stream back to the marked position.
*
* @param readlimit
* ignored.
* @see #markSupported()
* @see #reset()
*/
@Override
public void mark(int readlimit) {
mark = pos;
}
/**
* Indicates whether this stream supports the {@code mark()} and
* {@code reset()} methods. Returns {@code true} since this class supports
* these methods.
*
* @return always {@code true}.
* @see #mark(int)
* @see #reset()
*/
@Override
public boolean markSupported() {
return true;
}
/**
* Reads a single byte from the source byte array and returns it as an
* integer in the range from 0 to 255. Returns -1 if the end of the source
* array has been reached.
*
* @return the byte read or -1 if the end of this stream has been reached.
*/
@Override
public int read() {
return pos < count ? buf[pos++] & 0xFF : -1;
}
/**
* Reads at most {@code len} bytes from this stream and stores
* them in byte array {@code b} starting at {@code offset}. This
* implementation reads bytes from the source byte array.
*
* @param b
* the byte array in which to store the bytes read.
* @param offset
* the initial position in {@code b} to store the bytes read from
* this stream.
* @param length
* the maximum number of bytes to store in {@code b}.
* @return the number of bytes actually read or -1 if no bytes were read and
* the end of the stream was encountered.
* @throws IndexOutOfBoundsException
* if {@code offset < 0} or {@code length < 0}, or if
* {@code offset + length} is greater than the size of
* {@code b}.
* @throws NullPointerException
* if {@code b} is {@code null}.
*/
@Override
public int read(byte[] b, int offset, int length) {
if (b == null) {
throw new NullPointerException();
}
// avoid int overflow
if (offset < 0 || offset > b.length || length < 0
|| length > b.length - offset) {
throw new IndexOutOfBoundsException();
}
// Are there any bytes available?
if (this.pos >= this.count) {
return -1;
}
if (length == 0) {
return 0;
}
int copylen = this.count - pos < length ? this.count - pos : length;
System.arraycopy(buf, pos, b, offset, copylen);
pos += copylen;
return copylen;
}
/**
* Resets this stream to the last marked location. This implementation
* resets the position to either the marked position, the start position
* supplied in the constructor or 0 if neither has been provided.
*
* @see #mark(int)
*/
@Override
public void reset() {
pos = mark;
}
/**
* Skips {@code count} number of bytes in this InputStream. Subsequent
* {@code read()}s will not return these bytes unless {@code reset()} is
* used. This implementation skips {@code count} number of bytes in the
* target stream. It does nothing and returns 0 if {@code n} is negative.
*
* @param n
* the number of bytes to skip.
* @return the number of bytes actually skipped.
*/
@Override
public long skip(long n) {
if (n <= 0) {
return 0;
}
int temp = pos;
pos = this.count - pos < n ? this.count : (int) (pos + n);
return pos - temp;
}
}