1ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardpackage android.content.pm; 2ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 3ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardimport java.io.FilterInputStream; 4ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardimport java.io.IOException; 5ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardimport java.io.InputStream; 6103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Rootimport java.util.Arrays; 7ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 8ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward/** 9ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * A class that limits the amount of data that is read from an InputStream. When 10ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * the specified length is reached, the stream returns an EOF even if the 11ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * underlying stream still has more data. 12ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * 13ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * @hide 14ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward */ 15ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardpublic class LimitedLengthInputStream extends FilterInputStream { 16ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward /** 17ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * The end of the stream where we don't want to allow more data to be read. 18ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward */ 19103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root private final long mEnd; 20ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 21ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward /** 22ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * Current offset in the stream. 23ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward */ 24103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root private long mOffset; 25ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 26ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward /** 27ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * @param in underlying stream to wrap 28ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * @param offset offset into stream where data starts 29ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * @param length length of data at offset 30103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root * @throws IOException if an error occurred with the underlying stream 31ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward */ 32103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root public LimitedLengthInputStream(InputStream in, long offset, long length) throws IOException { 33ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward super(in); 34ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 35ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward if (in == null) { 36ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward throw new IOException("in == null"); 37ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 38ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 39ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward if (offset < 0) { 40103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root throw new IOException("offset < 0"); 41ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 42ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 43ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward if (length < 0) { 44103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root throw new IOException("length < 0"); 45103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root } 46103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root 47103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root if (length > Long.MAX_VALUE - offset) { 48103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root throw new IOException("offset + length > Long.MAX_VALUE"); 49ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 50ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 51ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward mEnd = offset + length; 52ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 53ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward skip(offset); 54ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward mOffset = offset; 55ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 56ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 57ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward @Override 58ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward public synchronized int read() throws IOException { 59ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward if (mOffset >= mEnd) { 60ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward return -1; 61ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 62ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 63ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward mOffset++; 64ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward return super.read(); 65ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 66ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 67ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward @Override 68ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward public int read(byte[] buffer, int offset, int byteCount) throws IOException { 69ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward if (mOffset >= mEnd) { 70ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward return -1; 71ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 72ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 73103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root final int arrayLength = buffer.length; 74103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root Arrays.checkOffsetAndCount(arrayLength, offset, byteCount); 75103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root 76103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root if (mOffset > Long.MAX_VALUE - byteCount) { 77103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root throw new IOException("offset out of bounds: " + mOffset + " + " + byteCount); 78103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root } 79103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root 80ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward if (mOffset + byteCount > mEnd) { 81103d53005e7a3c2735f4ac76fa9b795a7e7e39d7Kenny Root byteCount = (int) (mEnd - mOffset); 82ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 83ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 84ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward final int numRead = super.read(buffer, offset, byteCount); 85ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward mOffset += numRead; 86ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 87ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward return numRead; 88ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 89ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 90ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward @Override 91ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward public int read(byte[] buffer) throws IOException { 92ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward return read(buffer, 0, buffer.length); 93ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 94ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward} 95