116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropackage org.bouncycastle.util.io;
216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.io.ByteArrayOutputStream;
416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.io.IOException;
516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.io.InputStream;
616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.io.OutputStream;
716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro/**
953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro * Utility methods to assist with stream processing.
1053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro */
1116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropublic final class Streams
1216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro{
13bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro    private static int BUFFER_SIZE = 4096;
1416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
1553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    /**
1653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * Read stream till EOF is encountered.
1753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     *
1853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param inStr stream to be emptied.
1953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @throws IOException in case of underlying IOException.
2053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     */
2116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public static void drain(InputStream inStr)
2216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws IOException
2316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
2416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[] bs = new byte[BUFFER_SIZE];
2516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        while (inStr.read(bs, 0, bs.length) >= 0)
2616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
2716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
2816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
2916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
3053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    /**
3153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * Read stream fully, returning contents in a byte array.
3253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     *
3353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param inStr stream to be read.
3453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @return a byte array representing the contents of inStr.
3553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @throws IOException in case of underlying IOException.
3653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     */
3716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public static byte[] readAll(InputStream inStr)
3816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws IOException
3916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
4016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        ByteArrayOutputStream buf = new ByteArrayOutputStream();
4116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        pipeAll(inStr, buf);
4216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return buf.toByteArray();
4316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
4416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
4553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    /**
4653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * Read from inStr up to a maximum number of bytes, throwing an exception if more the maximum amount
4753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * of requested data is available.
4853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     *
4953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param inStr stream to be read.
5053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param limit maximum number of bytes that can be read.
5153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @return a byte array representing the contents of inStr.
5253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @throws IOException in case of underlying IOException, or if limit is reached on inStr still has data in it.
5353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     */
5416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public static byte[] readAllLimited(InputStream inStr, int limit)
5516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws IOException
5616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
5716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        ByteArrayOutputStream buf = new ByteArrayOutputStream();
5816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        pipeAllLimited(inStr, limit, buf);
5916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return buf.toByteArray();
6016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
6116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
6253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    /**
6353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * Fully read in buf's length in data, or up to EOF, whichever occurs first,
6453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     *
6553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param inStr the stream to be read.
6653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param buf the buffer to be read into.
6753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @return the number of bytes read into the buffer.
6853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @throws IOException in case of underlying IOException.
6953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     */
7016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public static int readFully(InputStream inStr, byte[] buf)
7116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws IOException
7216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
7316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return readFully(inStr, buf, 0, buf.length);
7416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
7516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
7653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    /**
7753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * Fully read in len's bytes of data into buf, or up to EOF, whichever occurs first,
7853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     *
7953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param inStr the stream to be read.
8053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param buf the buffer to be read into.
8153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param off offset into buf to start putting bytes into.
8253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param len  the number of bytes to be read.
8353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @return the number of bytes read into the buffer.
8453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @throws IOException in case of underlying IOException.
8553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     */
8616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public static int readFully(InputStream inStr, byte[] buf, int off, int len)
8716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws IOException
8816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
8916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int totalRead = 0;
9016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        while (totalRead < len)
9116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
9216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            int numRead = inStr.read(buf, off + totalRead, len - totalRead);
9316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (numRead < 0)
9416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
9516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                break;
9616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
9716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            totalRead += numRead;
9816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
9916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return totalRead;
10016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
10116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
10253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    /**
10353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * Write the full contents of inStr to the destination stream outStr.
10453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     *
10553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param inStr source input stream.
10653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param outStr destination output stream.
10753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @throws IOException in case of underlying IOException.
10853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     */
10916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public static void pipeAll(InputStream inStr, OutputStream outStr)
11016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws IOException
11116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
11216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[] bs = new byte[BUFFER_SIZE];
11316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int numRead;
11416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
11516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
11616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            outStr.write(bs, 0, numRead);
11716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
11816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
11916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
12053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    /**
12153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * Write up to limit bytes of data from inStr to the destination stream outStr.
12253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     *
12353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param inStr source input stream.
12453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param limit the maximum number of bytes allowed to be read.
12553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @param outStr destination output stream.
12653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     * @throws IOException in case of underlying IOException, or if limit is reached on inStr still has data in it.
12753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro     */
12816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public static long pipeAllLimited(InputStream inStr, long limit, OutputStream outStr)
12916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        throws IOException
13016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
13116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        long total = 0;
13216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[] bs = new byte[BUFFER_SIZE];
13316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int numRead;
13416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
13516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
136bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            if ((limit - total) < numRead)
13716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
13816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                throw new StreamOverflowException("Data Overflow");
13916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
140bdb7b3d37025690a0434040b4e0d0623d9fa74afSergio Giro            total += numRead;
14116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            outStr.write(bs, 0, numRead);
14216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
14316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return total;
14416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
1454caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
1464caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    public static void writeBufTo(ByteArrayOutputStream buf, OutputStream output)
1474caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        throws IOException
1484caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    {
1494caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        buf.writeTo(output);
1504caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    }
15116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro}
152