commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject svn commit: r1483389 - in /commons/proper/io/trunk/src: changes/changes.xml main/java/org/apache/commons/io/input/MaxBytesInputStream.java test/java/org/apache/commons/io/input/MaxBytesInputStreamTest.java
Date Thu, 16 May 2013 14:29:27 GMT
Author: sebb
Date: Thu May 16 14:29:26 2013
New Revision: 1483389

URL: http://svn.apache.org/r1483389
Log:
IO-339 MaxBytesInputStream to limit size of bytes read

Added:
    commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/MaxBytesInputStream.java
  (with props)
    commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/MaxBytesInputStreamTest.java
  (with props)
Modified:
    commons/proper/io/trunk/src/changes/changes.xml

Modified: commons/proper/io/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/changes/changes.xml?rev=1483389&r1=1483388&r2=1483389&view=diff
==============================================================================
--- commons/proper/io/trunk/src/changes/changes.xml (original)
+++ commons/proper/io/trunk/src/changes/changes.xml Thu May 16 14:29:26 2013
@@ -47,6 +47,9 @@ The <action> type attribute can be add,u
   <body>
     <!-- The release date is the date RC is cut -->
     <release version="2.5" date="2013-??-??" description="New features and bug fixes.">
   
+      <action issue="IO-339" dev="sebb" type="add" due-to="Ken Weiner">
+        MaxBytesInputStream to limit size of bytes read
+      </action>            
       <action issue="IO-381" dev="ggregory" type="add">
         Add FileUtils.copyInputStreamToFile API with option to leave the source open.
         See copyInputStreamToFile(final InputStream source, final File destination, boolean
closeSource)

Added: commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/MaxBytesInputStream.java
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/MaxBytesInputStream.java?rev=1483389&view=auto
==============================================================================
--- commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/MaxBytesInputStream.java
(added)
+++ commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/MaxBytesInputStream.java
Thu May 16 14:29:26 2013
@@ -0,0 +1,63 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An input stream that will end when the amount of bytes read reaches
+ * the configured number of maxBytes.
+ * This is useful for preventing OutOfMemoryExceptions when downloading
+ * very large files in cases where getting partial content is acceptable.
+ */
+public class MaxBytesInputStream extends CountingInputStream {
+    private final long maxBytes;
+
+    public MaxBytesInputStream(InputStream is, long maxBytes) {
+        super(is);
+        this.maxBytes = maxBytes;
+    }
+
+    @Override
+    public int read() throws IOException {
+        if (getByteCount() < this.maxBytes) {
+            return super.read();
+        }
+        return -1;
+    }
+
+    @Override
+    public int read(byte[] b) throws IOException {
+        return this.read(b, 0, b.length);
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        long remain = this.maxBytes - getByteCount();
+        if (remain > 0) {
+            if (remain < len) { // avoid reading past max
+                return super.read(b, off, (int) remain);                
+            } else {
+                return super.read(b, off, len);
+            }
+        }
+        return -1;
+    }
+}
\ No newline at end of file

Propchange: commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/MaxBytesInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/MaxBytesInputStream.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/MaxBytesInputStreamTest.java
URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/MaxBytesInputStreamTest.java?rev=1483389&view=auto
==============================================================================
--- commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/MaxBytesInputStreamTest.java
(added)
+++ commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/MaxBytesInputStreamTest.java
Thu May 16 14:29:26 2013
@@ -0,0 +1,250 @@
+/*
+ * 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.commons.io.input;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.NullOutputStream;
+
+/**
+ * Tests the MaxBytesInputStream.
+ *
+ * @version $Id$
+ */
+public class MaxBytesInputStreamTest extends TestCase {
+
+    public MaxBytesInputStreamTest(final String name) {
+        super(name);
+    }
+
+    public void testCounting() throws Exception {
+        final String text = "A piece of text";
+        final byte[] bytes = text.getBytes();
+        final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, text.length());
+
+        // have to declare this larger as we're going to read
+        // off the end of the stream and input stream seems
+        // to do bounds checking
+        final byte[] result = new byte[21];
+
+        final byte[] ba = new byte[5];
+        int found = cis.read(ba);
+        System.arraycopy(ba, 0, result, 0, 5);
+        assertEquals( found, cis.getCount() );
+
+        final int value = cis.read();
+        found++;
+        result[5] = (byte)value;
+        assertEquals( found, cis.getCount() );
+
+        found += cis.read(result, 6, 5);
+        assertEquals( found, cis.getCount() );
+
+        found += cis.read(result, 11, 10); // off the end
+        assertEquals( found, cis.getCount() );
+
+        // trim to get rid of the 6 empty values
+        final String textResult = new String(result).trim();
+        assertEquals(textResult, text);
+        cis.close();
+    }
+
+
+    /**
+     * Test for files > 2GB in size - see issue IO-84
+     */
+    public void testLargeFiles_IO84() throws Exception {
+        final long size = (long)Integer.MAX_VALUE + (long)1;
+        final NullInputStream mock    = new NullInputStream(size);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(mock, size);
+        final OutputStream out        = new NullOutputStream();
+
+        // Test integer methods
+        IOUtils.copyLarge(cis, out);
+        try {
+            cis.getCount();
+            fail("Expected getCount() to throw an ArithmeticException");
+        } catch (final ArithmeticException ae) {
+            // expected result
+        }
+        try {
+            cis.resetCount();
+            fail("Expected resetCount() to throw an ArithmeticException");
+        } catch (final ArithmeticException ae) {
+            // expected result
+        }
+
+        mock.close();
+
+        // Test long methods
+        IOUtils.copyLarge(cis, out);
+        assertEquals("getByteCount()",   size, cis.getByteCount());
+        assertEquals("resetByteCount()", size, cis.resetByteCount());
+    }
+
+    public void testResetting() throws Exception {
+        final String text = "A piece of text";
+        final byte[] bytes = text.getBytes();
+        final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, bytes.length);
+
+        final byte[] result = new byte[bytes.length];
+
+        int found = cis.read(result, 0, 5);
+        assertEquals( found, cis.getCount() );
+
+        final int count = cis.resetCount();
+        found = cis.read(result, 6, 5);
+        assertEquals( found, count );
+        cis.close();
+    }
+
+    public void testZeroLength1() throws Exception {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, 0);
+
+        final int found = cis.read();
+        assertEquals(-1, found);
+        assertEquals(0, cis.getCount());
+        cis.close();
+    }
+
+    public void testZeroLength2() throws Exception {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, 0);
+
+        final byte[] result = new byte[10];
+
+        final int found = cis.read(result);
+        assertEquals(-1, found);
+        assertEquals(0, cis.getCount());
+        cis.close();
+    }
+
+    public void testZeroLength3() throws Exception {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[0]);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, 0);
+
+        final byte[] result = new byte[10];
+
+        final int found = cis.read(result, 0, 5);
+        assertEquals(-1, found);
+        assertEquals(0, cis.getCount());
+        cis.close();
+    }
+
+    public void testEOF1() throws Exception {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[2]);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, 2);
+
+        int found = cis.read();
+        assertEquals(0, found);
+        assertEquals(1, cis.getCount());
+        found = cis.read();
+        assertEquals(0, found);
+        assertEquals(2, cis.getCount());
+        found = cis.read();
+        assertEquals(-1, found);
+        assertEquals(2, cis.getCount());
+        cis.close();
+    }
+
+    public void testEOF2() throws Exception {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[2]);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, 2);
+
+        final byte[] result = new byte[10];
+
+        final int found = cis.read(result);
+        assertEquals(2, found);
+        assertEquals(2, cis.getCount());
+        cis.close();
+    }
+
+    public void testEOF3() throws Exception {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[2]);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, 2);
+
+        final byte[] result = new byte[10];
+
+        final int found = cis.read(result, 0, 5);
+        assertEquals(2, found);
+        assertEquals(2, cis.getCount());
+        cis.close();
+    }
+
+    public void testMaxZero() throws Exception {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[2]);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, 0);
+
+        final byte[] result = new byte[10];
+
+        final int found = cis.read(result, 0, 5);
+        assertEquals(-1, found);
+        assertEquals(0, cis.getCount());
+        cis.close();
+    }
+
+    public void testMax1() throws Exception {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[20]);
+        final int max = 4;
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, max);
+
+        final byte[] result = new byte[10];
+
+        final int found = cis.read(result, 0, 5);
+        assertEquals(max, found);
+        assertEquals(max, cis.getCount());
+        cis.close();
+    }
+
+    public void testMax1b() throws Exception {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(new byte[20]);
+        final int max = 4;
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, max);
+
+        final byte[] result = new byte[10];
+
+        final int found = cis.read(result);
+        assertEquals(max, found);
+        assertEquals(max, cis.getCount());
+        cis.close();
+    }
+
+    public void testSkipping() throws IOException {
+        final String text = "Hello World!";
+        final byte[] bytes = text.getBytes();
+        final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+        final MaxBytesInputStream cis = new MaxBytesInputStream(bais, 100);
+
+        assertEquals(6,cis.skip(6));
+        assertEquals(6,cis.getCount());
+        final byte[] result = new byte[6];
+        cis.read(result);
+
+        assertEquals("World!",new String(result));
+        assertEquals(12,cis.getCount());
+        cis.close();
+    }
+
+}

Propchange: commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/MaxBytesInputStreamTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/MaxBytesInputStreamTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision



Mime
View raw message