Move readFullyAndClose method into LUNI utils' InputStreamHelper, and roll the input stream exposer code into there too.
Replace a number of places that read the full stream with calls to the new helper.
Part of HARMONY-6393 (fix "new byte[in.available()]" anti-pattern)

git-svn-id: https://svn.apache.org/repos/asf/harmony/enhanced/classlib/trunk@887293 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/modules/archive/src/main/java/java/util/jar/JarFile.java b/modules/archive/src/main/java/java/util/jar/JarFile.java
index 0fabd60..bebc82e 100644
--- a/modules/archive/src/main/java/java/util/jar/JarFile.java
+++ b/modules/archive/src/main/java/java/util/jar/JarFile.java
@@ -17,19 +17,19 @@
 
 package java.util.jar;
 
-import java.io.ByteArrayOutputStream;
-import java.util.List;
-import java.util.ArrayList;
 import java.io.File;
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 import org.apache.harmony.archive.internal.nls.Messages;
 import org.apache.harmony.archive.util.Util;
+import org.apache.harmony.luni.util.InputStreamHelper;
 
 /**
  * {@code JarFile} is used to read jar entries and their associated data from
@@ -282,42 +282,6 @@
         return (JarEntry) getEntry(name);
     }
 
-    /*
-     * Drains the entire content from the given input stream and returns it as a
-     * byte[]. The stream is closed after being drained, or if an IOException
-     * occurs.
-     */
-    private byte[] getAllBytesFromStreamAndClose(InputStream is)
-            throws IOException {
-        try {
-            // Initial read
-            byte[] buffer = new byte[1024];
-            int count = is.read(buffer);
-            int nextByte = is.read();
-
-            // Did we get it all in one read?
-            if (nextByte == -1) {
-                byte[] dest = new byte[count];
-                System.arraycopy(buffer, 0, dest, 0, count);
-                return dest;
-            }
-
-            // Requires additional reads
-            ByteArrayOutputStream baos = new ByteArrayOutputStream(count * 2);
-            baos.write(buffer, 0, count);
-            baos.write(nextByte);
-            while (true) {
-                count = is.read(buffer);
-                if (count == -1) {
-                    return baos.toByteArray();
-                }
-                baos.write(buffer, 0, count);
-            }
-        } finally {
-            is.close();
-        }
-    }
-
     /**
      * Returns the {@code Manifest} object associated with this {@code JarFile}
      * or {@code null} if no MANIFEST entry exists.
@@ -340,7 +304,8 @@
         try {
             InputStream is = super.getInputStream(manifestEntry);
             if (verifier != null) {
-                verifier.addMetaEntry(manifestEntry.getName(), getAllBytesFromStreamAndClose(is));
+                verifier.addMetaEntry(manifestEntry.getName(),
+                        InputStreamHelper.readFullyAndClose(is));
                 is = super.getInputStream(manifestEntry);
             }
             try {
@@ -392,7 +357,7 @@
                                 || Util.asciiEndsWithIgnoreCase(entryName, ".RSA"))) {
                     signed = true;
                     InputStream is = super.getInputStream(entry);
-                    byte[] buf = getAllBytesFromStreamAndClose(is);
+                    byte[] buf = InputStreamHelper.readFullyAndClose(is);
                     verifier.addMetaEntry(entryName, buf);
                 }
             }
diff --git a/modules/archive/src/main/java/java/util/jar/Manifest.java b/modules/archive/src/main/java/java/util/jar/Manifest.java
index 7f6437d..48dc8c8 100644
--- a/modules/archive/src/main/java/java/util/jar/Manifest.java
+++ b/modules/archive/src/main/java/java/util/jar/Manifest.java
@@ -30,7 +30,7 @@
 import java.util.Map;
 
 import org.apache.harmony.archive.internal.nls.Messages;
-import org.apache.harmony.luni.util.InputStreamExposer;
+import org.apache.harmony.luni.util.InputStreamHelper;
 import org.apache.harmony.luni.util.ThreadLocalCache;
 
 /**
@@ -209,7 +209,7 @@
         byte[] buf;
         // Try to read get a reference to the bytes directly
         try {
-            buf = InputStreamExposer.expose(is);
+            buf = InputStreamHelper.expose(is);
         } catch (UnsupportedOperationException uoe) {
             buf = readFully(is);
         }
diff --git a/modules/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java b/modules/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java
deleted file mode 100644
index 0ff073c..0000000
--- a/modules/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  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.harmony.luni.util;
-
-import java.io.ByteArrayInputStream;
-
-/**
- * The extension of <code>ByteArrayInputStream</code> which exposes an
- * underlying buffer.
- */
-public class ExposedByteArrayInputStream extends ByteArrayInputStream {
-
-    /**
-     * @see java.io.ByteArrayInputStream(byte[])
-     */
-    public ExposedByteArrayInputStream(byte buf[]) {
-        super(buf);
-    }
-
-    /**
-     * @see java.io.ByteArrayInputStream(byte[], int, int)
-     */
-    public ExposedByteArrayInputStream(byte buf[], int offset, int length) {
-        super(buf, offset, length);
-    }
-
-    /**
-     * Reads the whole stream and returns the stream snapshot.
-     */
-    public synchronized byte[] expose() {
-        if (pos == 0 && count == buf.length) {
-            skip(count);
-            return buf;
-        }
-
-        final int available = available();
-        final byte[] buffer = new byte[available];
-        System.arraycopy(buf, pos, buffer, 0, available);
-        skip(available);
-        return buffer;
-    }
-}
diff --git a/modules/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java b/modules/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java
deleted file mode 100644
index 61dfeee..0000000
--- a/modules/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- *  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.harmony.luni.util;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Field;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-/**
- * The class contains static {@link java.io.InputStream} utilities.
- */
-public class InputStreamExposer {
-
-    /**
-     * Provides access to a protected underlying buffer of
-     * <code>ByteArrayInputStream</code>.
-     */
-    private static final Field BAIS_BUF;
-
-    /**
-     * Provides access to a protected position in the underlying buffer of
-     * <code>ByteArrayInputStream</code>.
-     */
-    private static final Field BAIS_POS;
-
-    static {
-        final Field[] f = new Field[2];
-        AccessController.doPrivileged(new PrivilegedAction<Object>() {
-            public Object run() {
-                try {
-                    f[0] = ByteArrayInputStream.class.getDeclaredField("buf");
-                    f[0].setAccessible(true);
-                    f[1] = ByteArrayInputStream.class.getDeclaredField("pos");
-                    f[1].setAccessible(true);
-                } catch (NoSuchFieldException nsfe) {
-                    throw new InternalError(nsfe.getLocalizedMessage());
-                }
-                return null;
-            }
-        });
-        BAIS_BUF = f[0];
-        BAIS_POS = f[1];
-    }
-
-    /**
-     * Reads all bytes from {@link java.io.ByteArrayInputStream} using its
-     * underlying buffer directly.
-     * 
-     * @return an underlying buffer, if a current position is at the buffer
-     *         beginning, and an end position is at the buffer end, or a copy of
-     *         the underlying buffer part.
-     */
-    private static byte[] expose(ByteArrayInputStream bais) {
-        byte[] buffer, buf;
-        int pos;
-        synchronized (bais) {
-            int available = bais.available();
-            try {
-                buf = (byte[]) BAIS_BUF.get(bais);
-                pos = BAIS_POS.getInt(bais);
-            } catch (IllegalAccessException iae) {
-                throw new InternalError(iae.getLocalizedMessage());
-            }
-            if (pos == 0 && available == buf.length) {
-                buffer = buf;
-            } else {
-                buffer = new byte[available];
-                System.arraycopy(buf, pos, buffer, 0, available);
-            }
-            bais.skip(available);
-        }
-        return buffer;
-    }
-
-    /**
-     * The utility method for reading the whole input stream into a snapshot
-     * buffer. To speed up the access it works with an underlying buffer for a
-     * given {@link java.io.ByteArrayInputStream}.
-     * 
-     * @param is
-     *            the stream to be read.
-     * @return the snapshot wrapping the buffer where the bytes are read to.
-     * @throws UnsupportedOperationException if the input stream data cannot be exposed
-     */
-    public static byte[] expose(InputStream is) throws IOException, UnsupportedOperationException {
-        if (is instanceof ExposedByteArrayInputStream) {
-            return ((ExposedByteArrayInputStream) is).expose();
-        }
-
-        if (is.getClass().equals(ByteArrayInputStream.class)) {
-            return expose((ByteArrayInputStream) is);
-        }
-
-        // We don't know how to do this
-        throw new UnsupportedOperationException();
-    }
-}
diff --git a/modules/luni/src/main/java/org/apache/harmony/luni/util/InputStreamHelper.java b/modules/luni/src/main/java/org/apache/harmony/luni/util/InputStreamHelper.java
new file mode 100644
index 0000000..98835f7
--- /dev/null
+++ b/modules/luni/src/main/java/org/apache/harmony/luni/util/InputStreamHelper.java
@@ -0,0 +1,199 @@
+/*
+ *  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.harmony.luni.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * The class contains static {@link java.io.InputStream} utilities.
+ */
+public class InputStreamHelper {
+
+    /**
+     * Provides access to a protected underlying buffer of
+     * <code>ByteArrayInputStream</code>.
+     */
+    private static final Field BAIS_BUF;
+
+    /**
+     * Provides access to a protected position in the underlying buffer of
+     * <code>ByteArrayInputStream</code>.
+     */
+    private static final Field BAIS_POS;
+
+    static {
+        final Field[] f = new Field[2];
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            public Object run() {
+                try {
+                    f[0] = ByteArrayInputStream.class.getDeclaredField("buf"); //$NON-NLS-1$
+                    f[0].setAccessible(true);
+                    f[1] = ByteArrayInputStream.class.getDeclaredField("pos"); //$NON-NLS-1$
+                    f[1].setAccessible(true);
+                } catch (NoSuchFieldException nsfe) {
+                    throw new InternalError(nsfe.getLocalizedMessage());
+                }
+                return null;
+            }
+        });
+        BAIS_BUF = f[0];
+        BAIS_POS = f[1];
+    }
+
+    /**
+     * The extension of <code>ByteArrayInputStream</code> which exposes an
+     * underlying buffer.
+     */
+    static class ExposedByteArrayInputStream extends ByteArrayInputStream {
+
+        /**
+         * @see java.io.ByteArrayInputStream(byte[])
+         */
+        public ExposedByteArrayInputStream(byte buf[]) {
+            super(buf);
+        }
+
+        /**
+         * @see java.io.ByteArrayInputStream(byte[], int, int)
+         */
+        public ExposedByteArrayInputStream(byte buf[], int offset, int length) {
+            super(buf, offset, length);
+        }
+
+        /**
+         * Reads the whole stream and returns the stream snapshot.
+         */
+        public synchronized byte[] expose() {
+            if (pos == 0 && count == buf.length) {
+                skip(count);
+                return buf;
+            }
+
+            final int available = available();
+            final byte[] buffer = new byte[available];
+            System.arraycopy(buf, pos, buffer, 0, available);
+            skip(available);
+            return buffer;
+        }
+    }
+
+    /**
+     * Reads all bytes from {@link java.io.ByteArrayInputStream} using its
+     * underlying buffer directly.
+     * 
+     * @return an underlying buffer, if a current position is at the buffer
+     *         beginning, and an end position is at the buffer end, or a copy of
+     *         the underlying buffer part.
+     */
+    private static byte[] expose(ByteArrayInputStream bais) {
+        byte[] buffer, buf;
+        int pos;
+        synchronized (bais) {
+            int available = bais.available();
+            try {
+                buf = (byte[]) BAIS_BUF.get(bais);
+                pos = BAIS_POS.getInt(bais);
+            } catch (IllegalAccessException iae) {
+                throw new InternalError(iae.getLocalizedMessage());
+            }
+            if (pos == 0 && available == buf.length) {
+                buffer = buf;
+            } else {
+                buffer = new byte[available];
+                System.arraycopy(buf, pos, buffer, 0, available);
+            }
+            bais.skip(available);
+        }
+        return buffer;
+    }
+
+    /**
+     * The utility method for reading the whole input stream into a snapshot
+     * buffer. To speed up the access it works with an underlying buffer for a
+     * given {@link java.io.ByteArrayInputStream}.
+     * 
+     * @param is
+     *            the stream to be read.
+     * @return the snapshot wrapping the buffer where the bytes are read to.
+     * @throws UnsupportedOperationException
+     *             if the input stream data cannot be exposed
+     */
+    public static byte[] expose(InputStream is) throws IOException,
+            UnsupportedOperationException {
+        if (is instanceof ExposedByteArrayInputStream) {
+            return ((ExposedByteArrayInputStream) is).expose();
+        }
+
+        if (is.getClass().equals(ByteArrayInputStream.class)) {
+            return expose((ByteArrayInputStream) is);
+        }
+
+        // We don't know how to do this
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Reads all the bytes from the given input stream.
+     * 
+     * Calls read multiple times on the given input stream until it receives an
+     * end of file marker. Returns the combined results as a byte array. Note
+     * that this method may block if the underlying stream read blocks.
+     * 
+     * @param is
+     *            the input stream to be read.
+     * @return the content of the stream as a byte array.
+     * @throws IOException
+     *             if a read error occurs.
+     */
+    public static byte[] readFullyAndClose(InputStream is) throws IOException {
+
+        try {
+            // Initial read
+            byte[] buffer = new byte[1024];
+            int count = is.read(buffer);
+            int nextByte = is.read();
+
+            // Did we get it all in one read?
+            if (nextByte == -1) {
+                byte[] dest = new byte[count];
+                System.arraycopy(buffer, 0, dest, 0, count);
+                return dest;
+            }
+
+            // Requires additional reads
+            ByteArrayOutputStream baos = new ByteArrayOutputStream(count * 2);
+            baos.write(buffer, 0, count);
+            baos.write(nextByte);
+            while (true) {
+                count = is.read(buffer);
+                if (count == -1) {
+                    return baos.toByteArray();
+                }
+                baos.write(buffer, 0, count);
+            }
+        } finally {
+            is.close();
+        }
+    }
+}
diff --git a/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/SerializationStressTest.java b/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/SerializationStressTest.java
index 570b7c2..5fb61a6 100644
--- a/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/SerializationStressTest.java
+++ b/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/SerializationStressTest.java
@@ -58,6 +58,8 @@
 import java.util.TreeSet;
 import java.util.Vector;
 
+import org.apache.harmony.luni.util.InputStreamHelper;
+
 /**
  * Automated Test Suite for class java.io.ObjectOutputStream
  * 
@@ -658,33 +660,25 @@
 		assertTrue("resolved class 3", resolvedClasses[2] == Number.class);
 	}
 
-	public void test_reset() {
-		try {
-			oos.reset();
-			oos.writeObject("R");
-			oos.reset();
-			oos.writeByte(24);
-			oos.close();
+    public void test_reset() throws IOException, ClassNotFoundException {
+        oos.reset();
+        oos.writeObject("R");
+        oos.reset();
+        oos.writeByte(24);
+        oos.close();
 
-			DataInputStream dis = new DataInputStream(loadStream());
-			byte[] input = new byte[dis.available()];
-			dis.readFully(input);
-			byte[] result = new byte[] { (byte) 0xac, (byte) 0xed, (byte) 0,
-					(byte) 5, (byte) 0x79, (byte) 0x74, (byte) 0, (byte) 1,
-					(byte) 'R', (byte) 0x79, (byte) 0x77, (byte) 1, (byte) 24 };
-			assertTrue("incorrect output", Arrays.equals(input, result));
+        DataInputStream dis = new DataInputStream(loadStream());
+        byte[] input = InputStreamHelper.readFullyAndClose(dis);
+        byte[] result = new byte[] { (byte) 0xac, (byte) 0xed, (byte) 0,
+                (byte) 5, (byte) 0x79, (byte) 0x74, (byte) 0, (byte) 1,
+                (byte) 'R', (byte) 0x79, (byte) 0x77, (byte) 1, (byte) 24 };
+        assertTrue("incorrect output", Arrays.equals(input, result));
 
-			ois = new ObjectInputStreamSubclass(loadStream());
-			assertEquals("Wrong result from readObject()", "R", ois.readObject()
-					);
-			assertEquals("Wrong result from readByte()", 24, ois.readByte());
-			ois.close();
-		} catch (IOException e1) {
-			fail("IOException : " + e1.getMessage());
-		} catch (ClassNotFoundException e2) {
-			fail("ClassNotFoundException : " + e2.getMessage());
-		}
-	}
+        ois = new ObjectInputStreamSubclass(loadStream());
+        assertEquals("Wrong result from readObject()", "R", ois.readObject());
+        assertEquals("Wrong result from readByte()", 24, ois.readByte());
+        ois.close();
+    }
 
 	public void test_serialVersionUID(Class clazz, long svUID) throws Exception {
 		final String idWrong = "serialVersionUID is wrong for: ";
diff --git a/modules/rmi/META-INF/MANIFEST.MF b/modules/rmi/META-INF/MANIFEST.MF
index f36a610..25c2fda 100644
--- a/modules/rmi/META-INF/MANIFEST.MF
+++ b/modules/rmi/META-INF/MANIFEST.MF
@@ -23,6 +23,7 @@
  javax.net,
  javax.net.ssl,
  org.apache.harmony.kernel.vm,
+ org.apache.harmony.luni.util,
  org.apache.harmony.testframework.serialization;hy_usage=test;resolution:=optional
 Export-Package: java.rmi,
  java.rmi.activation,
diff --git a/modules/rmi/src/main/java/java/rmi/server/RMIClassLoader.java b/modules/rmi/src/main/java/java/rmi/server/RMIClassLoader.java
index fd1adcd..1fdbe22 100644
--- a/modules/rmi/src/main/java/java/rmi/server/RMIClassLoader.java
+++ b/modules/rmi/src/main/java/java/rmi/server/RMIClassLoader.java
@@ -29,6 +29,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
+import org.apache.harmony.luni.util.InputStreamHelper;
 import org.apache.harmony.rmi.DefaultRMIClassLoaderSpi;
 import org.apache.harmony.rmi.internal.nls.Messages;
 
@@ -210,9 +211,7 @@
             // resource not found
             return null;
         }
-        Object obj = null;
-        byte[] buf = new byte[in.available()];
-        in.read(buf);
+        byte[] buf = InputStreamHelper.readFullyAndClose(in);
         String str = new String(buf, "UTF-8"); //$NON-NLS-1$
         StringTokenizer tok = new StringTokenizer(str, "\n\r"); //$NON-NLS-1$
 
diff --git a/modules/security/src/main/java/common/org/apache/harmony/security/utils/JarUtils.java b/modules/security/src/main/java/common/org/apache/harmony/security/utils/JarUtils.java
index b6b7dab..b3f13cc 100644
--- a/modules/security/src/main/java/common/org/apache/harmony/security/utils/JarUtils.java
+++ b/modules/security/src/main/java/common/org/apache/harmony/security/utils/JarUtils.java
@@ -38,6 +38,7 @@
 
 import javax.security.auth.x500.X500Principal;
 
+import org.apache.harmony.luni.util.InputStreamHelper;
 import org.apache.harmony.security.asn1.BerInputStream;
 import org.apache.harmony.security.internal.nls.Messages;
 import org.apache.harmony.security.pkcs7.ContentInfo;
@@ -144,8 +145,7 @@
         // Otherwise, compute the message digest on the data.
         List atr = sigInfo.getAuthenticatedAttributes();
 
-        byte[] sfBytes = new byte[signature.available()];
-        signature.read(sfBytes);
+        byte[] sfBytes = InputStreamHelper.readFullyAndClose(signature);
 
         if (atr == null) {
             sig.update(sfBytes);    
diff --git a/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/SecureClassLoader2Test.java b/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/SecureClassLoader2Test.java
index 65f6c9a..96c27ed 100644
--- a/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/SecureClassLoader2Test.java
+++ b/modules/security/src/test/api/java/org/apache/harmony/security/tests/java/security/SecureClassLoader2Test.java
@@ -17,7 +17,6 @@
 
 package org.apache.harmony.security.tests.java.security;
 
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -29,6 +28,8 @@
 import java.util.Enumeration;
 import java.util.jar.JarFile;
 
+import org.apache.harmony.luni.util.InputStreamHelper;
+
 import tests.support.Support_GetLocal;
 
 public class SecureClassLoader2Test extends junit.framework.TestCase {
@@ -61,47 +62,11 @@
 
         File file = Support_GetLocal.getLocalFile("hyts_security.jar");
         JarFile jar = new JarFile(file);
-        InputStream in = jar.getInputStream(jar
-                .getEntry("packA/SecurityTest.class"));
-        byte[] bytes = drain(in);
+        InputStream in = jar.getInputStream(jar.getEntry("packA/SecurityTest.class"));
+        byte[] bytes = InputStreamHelper.readFullyAndClose(in);
         Class c = myloader.define("packA.SecurityTest", bytes);
 		ProtectionDomain pd = c.getProtectionDomain();
 		assertNotNull("Expected dynamic policy", pd.getClassLoader());
 		assertNull("Expected null permissions", pd.getPermissions());
 	}
-
-    /*
-     * Drains the entire content from the given input stream and returns it as a
-     * byte[]. The stream is closed after being drained, or if an IOException
-     * occurs.
-     */
-    private byte[] drain(InputStream is) throws IOException {
-        try {
-            // Initial read
-            byte[] buffer = new byte[1024];
-            int count = is.read(buffer);
-            int nextByte = is.read();
-
-            // Did we get it all in one read?
-            if (nextByte == -1) {
-                byte[] dest = new byte[count];
-                System.arraycopy(buffer, 0, dest, 0, count);
-                return dest;
-            }
-
-            // Requires additional reads
-            ByteArrayOutputStream baos = new ByteArrayOutputStream(count * 2);
-            baos.write(buffer, 0, count);
-            baos.write(nextByte);
-            while (true) {
-                count = is.read(buffer);
-                if (count == -1) {
-                    return baos.toByteArray();
-                }
-                baos.write(buffer, 0, count);
-            }
-        } finally {
-            is.close();
-        }
-    }
 }
\ No newline at end of file
diff --git a/modules/sound/src/main/java/org/apache/harmony/sound/utils/ProviderService.java b/modules/sound/src/main/java/org/apache/harmony/sound/utils/ProviderService.java
index 3a574c3..d65b657 100644
--- a/modules/sound/src/main/java/org/apache/harmony/sound/utils/ProviderService.java
+++ b/modules/sound/src/main/java/org/apache/harmony/sound/utils/ProviderService.java
@@ -17,12 +17,11 @@
 
 package org.apache.harmony.sound.utils;
 
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.InputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -31,6 +30,8 @@
 import java.util.List;
 import java.util.Properties;
 
+import org.apache.harmony.luni.util.InputStreamHelper;
+
 public class ProviderService {
 
     // Properties from sound.propertie file
@@ -145,7 +146,7 @@
                             try {
                                 InputStream in = urls.nextElement()
                                         .openStream();
-                                bytes = getAllBytesFromStreamAndClose(in);
+                                bytes = InputStreamHelper.readFullyAndClose(in);
                             } catch (IOException e) {
                                 continue;
                             }
@@ -172,41 +173,5 @@
     public static Properties getSoundProperties() {
         return devices;
     }
-    
-    /*
-     * Drains the entire content from the given input stream and returns it as a
-     * byte[]. The stream is closed after being drained, or if an IOException
-     * occurs.
-     */
-    private static byte[] getAllBytesFromStreamAndClose(InputStream is)
-            throws IOException {
-        try {
-            // Initial read
-            byte[] buffer = new byte[512];
-            int count = is.read(buffer);
-            int nextByte = is.read();
-
-            // Did we get it all in one read?
-            if (nextByte == -1) {
-                byte[] dest = new byte[count];
-                System.arraycopy(buffer, 0, dest, 0, count);
-                return dest;
-            }
-
-            // Requires additional reads
-            ByteArrayOutputStream baos = new ByteArrayOutputStream(count * 2);
-            baos.write(buffer, 0, count);
-            baos.write(nextByte);
-            while (true) {
-                count = is.read(buffer);
-                if (count == -1) {
-                    return baos.toByteArray();
-                }
-                baos.write(buffer, 0, count);
-            }
-        } finally {
-            is.close();
-        }
-    }
 
 }