com.amazonaws.util.LengthCheckInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aws-android-sdk-mobileanalytics Show documentation
Show all versions of aws-android-sdk-mobileanalytics Show documentation
Amazon Web Services SDK for Android
/*
* Copyright 2014-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 com.amazonaws.util;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.annotation.NotThreadSafe;
import com.amazonaws.AmazonClientException;
import com.amazonaws.internal.SdkFilterInputStream;
/**
* Used to perform length check to ensure the number of bytes read from the
* underlying input stream is the same as the expected total.
*/
@NotThreadSafe
public class LengthCheckInputStream extends SdkFilterInputStream {
public static final boolean INCLUDE_SKIPPED_BYTES = true;
public static final boolean EXCLUDE_SKIPPED_BYTES = false;
/**
* Total number of bytes expected to be read from the underlying input
* stream.
*/
private final long expectedLength;
/**
* True if skipped bytes are to be included as part of the data length;
* false otherwise.
*/
private final boolean includeSkipped;
/**
* The length of the data read from the underlying input stream so far.
*/
private long dataLength;
private long marked; // used for mark-and-reset purposes
/**
* Constructs an input stream that performs length check to ensure the
* number of bytes read from the underlying input stream is the same as the
* expected total.
*
* @param in
* the underlying input stream
* @param expectedLength
* the total length of the data in bytes expected to be read from
* the underlying input stream; must be non-negative.
* @param includeSkipped
* true if bytes skipped are to be considered as part of the data
* length; false otherwise. Typically, this parameter should be
* set to false for uploading data to AWS, but set to true for
* receiving data from AWS.
*/
public LengthCheckInputStream(InputStream in, long expectedLength,
boolean includeSkipped) {
super(in);
if (expectedLength < 0)
throw new IllegalArgumentException();
this.expectedLength = expectedLength;
this.includeSkipped = includeSkipped;
}
/**
* {@inheritDoc}
*
* @throws AmazonClientException
* if the data length read has exceeded the expected total, or
* if the total data length is not the same as the expected
* total.
*/
@Override
public int read() throws IOException {
final int c = super.read();
if (c >= 0)
dataLength++;
checkLength(c == -1);
return c;
}
/**
* {@inheritDoc}
*
* @throws AmazonClientException
* if the data length read has exceeded the expected total, or
* if the total data length is not the same as the expected
* total.
*/
@Override
public int read(byte[] b, int off, int len) throws IOException {
int readLen = super.read(b, off, len);
dataLength += readLen >= 0 ? readLen : 0;
checkLength(readLen == -1);
return readLen;
}
@Override
public void mark(int readlimit) {
super.mark(readlimit);
marked = dataLength;
}
@Override
public void reset() throws IOException {
super.reset();
if (super.markSupported()) {
dataLength = marked;
}
}
/**
* Checks the data length read so far against the expected total.
*
* @param eof
* true if end of stream has been encountered; false otherwise
*
* @throws AmazonClientException
* if the data length read has exceeded the expected total, or
* if the total data length is not the same as the expected
* total.
*/
private void checkLength(boolean eof) {
if (eof) {
if (dataLength != expectedLength) {
throw new AmazonClientException("Data read (" + dataLength
+ ") has a different length than the expected ("
+ expectedLength + ")");
}
} else if (dataLength > expectedLength) {
throw new AmazonClientException("More data read (" + dataLength
+ ") than expected (" + expectedLength + ")");
}
}
/**
* {@inheritDoc}
*
* @throws AmazonClientException
* if {@link #includeSkipped} is true and the data length
* skipped has exceeded the expected total.
*/
@Override
public long skip(long n) throws IOException {
final long skipped = super.skip(n);
if (includeSkipped && skipped > 0) {
dataLength += skipped;
checkLength(false);
}
return skipped;
}
}