summaryrefslogtreecommitdiffstats
path: root/luni
diff options
context:
space:
mode:
authorAndroid (Google) Code Review <android-gerrit@google.com>2009-12-14 14:35:24 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2009-12-14 14:35:24 -0800
commitee5af1749a3e4274baf177dc86d222c519086da9 (patch)
tree5c6ae61609d973098a4e14d237fe929309a05c7a /luni
parent97e18d454c30a7836315bfd40453eed826b2f4ec (diff)
parentf7c6911047d63bc76292f55ce538da32818dd931 (diff)
downloadlibcore-ee5af1749a3e4274baf177dc86d222c519086da9.zip
libcore-ee5af1749a3e4274baf177dc86d222c519086da9.tar.gz
libcore-ee5af1749a3e4274baf177dc86d222c519086da9.tar.bz2
Merge change I1d96b51e
* changes: Merge branch 'archive_888752' into archive_dalvik
Diffstat (limited to 'luni')
-rw-r--r--luni/src/main/java/org/apache/harmony/luni/InputStreamHelper.java199
1 files changed, 199 insertions, 0 deletions
diff --git a/luni/src/main/java/org/apache/harmony/luni/InputStreamHelper.java b/luni/src/main/java/org/apache/harmony/luni/InputStreamHelper.java
new file mode 100644
index 0000000..329b420
--- /dev/null
+++ b/luni/src/main/java/org/apache/harmony/luni/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();
+ }
+ }
+}