blob: c9ffe86fd62404a40f36436778409f3a9a05f374 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed 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 com.android.tradefed.util;
import com.android.tradefed.result.InputStreamSource;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.io.Writer;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipOutputStream;
import javax.xml.bind.DatatypeConverter;
/**
* Utility class for managing input streams.
*/
public class StreamUtil {
// 16K buffer size
private static final int BUF_SIZE = 16 * 1024;
private StreamUtil() {
}
/**
* Retrieves a {@link String} from an {@link InputStreamSource}.
*
* @param source the {@link InputStreamSource}
* @return a {@link String} containing the stream contents
* @throws IOException if failure occurred reading the stream
*/
public static String getStringFromSource(InputStreamSource source) throws IOException {
final InputStream stream = source.createInputStream();
final String contents;
try {
contents = getStringFromStream(stream);
} finally {
close(stream);
}
return contents;
}
/**
* Retrieves a {@link ByteArrayList} from an {@link InputStreamSource}.
*
* @param source the {@link InputStreamSource}
* @return a {@link ByteArrayList} containing the stream contents
* @throws IOException if failure occurred reading the stream
*/
public static ByteArrayList getByteArrayListFromSource(InputStreamSource source)
throws IOException {
final InputStream stream = source.createInputStream();
final ByteArrayList contents;
try {
contents = getByteArrayListFromStream(stream);
} finally {
close(stream);
}
return contents;
}
/**
* Retrieves a {@link String} from a character stream.
*
* @param stream the {@link InputStream}
* @return a {@link String} containing the stream contents
* @throws IOException if failure occurred reading the stream
*/
public static String getStringFromStream(InputStream stream) throws IOException {
Reader ir = new BufferedReader(new InputStreamReader(stream));
int irChar = -1;
StringBuilder builder = new StringBuilder();
while ((irChar = ir.read()) != -1) {
builder.append((char)irChar);
}
return builder.toString();
}
/**
* Retrieves a {@link ByteArrayList} from a byte stream.
*
* @param stream the {@link InputStream}
* @return a {@link ByteArrayList} containing the stream contents
* @throws IOException if failure occurred reading the stream
*/
public static ByteArrayList getByteArrayListFromStream(InputStream stream) throws IOException {
InputStream is = new BufferedInputStream(stream);
int inputByte = -1;
ByteArrayList list = new ByteArrayList();
while ((inputByte = is.read()) != -1) {
list.add((byte)inputByte);
}
list.trimToSize();
return list;
}
/**
* Copies contents of origStream to destStream.
* <p/>
* Recommended to provide a buffered stream for input and output
*
* @param inStream the {@link InputStream}
* @param outStream the {@link OutputStream}
* @throws IOException
*/
public static void copyStreams(InputStream inStream, OutputStream outStream)
throws IOException {
byte[] buf = new byte[BUF_SIZE];
int size = -1;
while ((size = inStream.read(buf)) != -1) {
outStream.write(buf, 0, size);
}
}
/**
* Copies contents of inStream to writer.
* <p/>
* Recommended to provide a buffered stream for input and output
*
* @param inStream the {@link InputStream}
* @param writer the {@link Writer} destination
* @throws IOException
*/
public static void copyStreamToWriter(InputStream inStream, Writer writer) throws IOException {
byte[] buf = new byte[BUF_SIZE];
int size = -1;
while ((size = inStream.read(buf)) != -1) {
writer.write(new String(buf, 0, size));
}
}
/**
* Gets the stack trace as a {@link String}.
*
* @param throwable the {@link Throwable} to convert.
* @return a {@link String} stack trace
*/
public static String getStackTrace(Throwable throwable) {
// dump the print stream results to the ByteArrayOutputStream, so contents can be evaluated
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PrintStream bytePrintStream = new PrintStream(outputStream);
throwable.printStackTrace(bytePrintStream);
return outputStream.toString();
}
/**
* @deprecated use {@link #close(Closeable)} instead.
*/
@Deprecated
public static void closeStream(OutputStream out) {
close(out);
}
/**
* @deprecated use {@link #close(Closeable)} instead.
*/
@Deprecated
public static void closeStream(InputStream in) {
close(in);
}
/**
* Attempts to flush the given output stream, and then closes it.
*
* @param outStream the {@link OutputStream}. No action taken if outStream is null.
*/
public static void flushAndCloseStream(OutputStream outStream) {
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e) {
// ignore
}
try {
outStream.close();
} catch (IOException e) {
// ignore
}
}
}
/**
* Closes given zip output stream.
*
* @param outStream the {@link ZipOutputStream}. No action taken if outStream is null.
*/
public static void closeZipStream(ZipOutputStream outStream) {
if (outStream != null) {
try {
outStream.closeEntry();
outStream.close();
} catch (IOException e) {
// ignore
}
}
}
/**
* Closes given gzip output stream.
*
* @param outStream the {@link ZipOutputStream}. No action taken if outStream is null.
*/
public static void closeGZipStream(GZIPOutputStream outStream) {
if (outStream != null) {
try {
outStream.finish();
outStream.close();
} catch (IOException e) {
// ignore
}
}
}
/**
* Closes the given {@link Closeable}.
*
* @param closeable the {@link Closeable}. No action taken if <code>null</code>.
*/
public static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
// ignore
}
}
}
/**
* Cancels the given {@link InputStreamSource} if non-null.
*/
public static void cancel(InputStreamSource outputSource) {
if (outputSource != null) {
outputSource.cancel();
}
}
/**
* Create a {@link OutputStream} that discards all writes.
*
* TODO: replace with guava's ByteStreams.nullOutputStream() when guava is updated.
*/
public static OutputStream nullOutputStream() {
return new OutputStream() {
/** Discards the specified byte. */
@Override public void write(int b) {
}
/** Discards the specified byte array. */
@Override public void write(byte[] b, int off, int len) {
}
};
}
/**
* Helper method to calculate md5 for a inputStream. The inputStream will be consumed and
* closed.
*
* @param inputSource used to create inputStream
* @return md5 of the stream
* @throws IOException
*/
public static String calculateMd5(InputStream inputSource) throws IOException {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("md5");
} catch (NoSuchAlgorithmException e) {
// This should not happen
throw new RuntimeException(e);
}
InputStream input = new BufferedInputStream(new DigestInputStream(inputSource, md));
byte[] buf = new byte[BUF_SIZE];
while (input.read(buf) != -1) {
// Read through the stream to update digest.
}
input.close();
String md5 = DatatypeConverter.printHexBinary(md.digest()).toLowerCase();
return md5;
}
}