1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.io.output; 18 19 import java.io.BufferedInputStream; 20 import java.io.IOException; 21 import java.io.InputStream; 22 import java.io.OutputStream; 23 24 /** 25 * Implements a ThreadSafe version of {@link AbstractByteArrayOutputStream} using instance synchronization. 26 */ 27 //@ThreadSafe 28 public class ByteArrayOutputStream extends AbstractByteArrayOutputStream { 29 30 /** 31 * Fetches entire contents of an {@link InputStream} and represent 32 * same data as result InputStream. 33 * <p> 34 * This method is useful where, 35 * </p> 36 * <ul> 37 * <li>Source InputStream is slow.</li> 38 * <li>It has network resources associated, so we cannot keep it open for 39 * long time.</li> 40 * <li>It has network timeout associated.</li> 41 * </ul> 42 * It can be used in favor of {@link #toByteArray()}, since it 43 * avoids unnecessary allocation and copy of byte[].<br> 44 * This method buffers the input internally, so there is no need to use a 45 * {@link BufferedInputStream}. 46 * 47 * @param input Stream to be fully buffered. 48 * @return A fully buffered stream. 49 * @throws IOException if an I/O error occurs. 50 * @since 2.0 51 */ toBufferedInputStream(final InputStream input)52 public static InputStream toBufferedInputStream(final InputStream input) 53 throws IOException { 54 return toBufferedInputStream(input, DEFAULT_SIZE); 55 } 56 57 /** 58 * Fetches entire contents of an {@link InputStream} and represent 59 * same data as result InputStream. 60 * <p> 61 * This method is useful where, 62 * </p> 63 * <ul> 64 * <li>Source InputStream is slow.</li> 65 * <li>It has network resources associated, so we cannot keep it open for 66 * long time.</li> 67 * <li>It has network timeout associated.</li> 68 * </ul> 69 * It can be used in favor of {@link #toByteArray()}, since it 70 * avoids unnecessary allocation and copy of byte[].<br> 71 * This method buffers the input internally, so there is no need to use a 72 * {@link BufferedInputStream}. 73 * 74 * @param input Stream to be fully buffered. 75 * @param size the initial buffer size 76 * @return A fully buffered stream. 77 * @throws IOException if an I/O error occurs. 78 * @since 2.5 79 */ toBufferedInputStream(final InputStream input, final int size)80 public static InputStream toBufferedInputStream(final InputStream input, final int size) 81 throws IOException { 82 try (ByteArrayOutputStream output = new ByteArrayOutputStream(size)) { 83 output.write(input); 84 return output.toInputStream(); 85 } 86 } 87 88 /** 89 * Constructs a new byte array output stream. The buffer capacity is 90 * initially {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary. 91 */ ByteArrayOutputStream()92 public ByteArrayOutputStream() { 93 this(DEFAULT_SIZE); 94 } 95 96 /** 97 * Constructs a new byte array output stream, with a buffer capacity of 98 * the specified size, in bytes. 99 * 100 * @param size the initial size 101 * @throws IllegalArgumentException if size is negative 102 */ ByteArrayOutputStream(final int size)103 public ByteArrayOutputStream(final int size) { 104 if (size < 0) { 105 throw new IllegalArgumentException("Negative initial size: " + size); 106 } 107 synchronized (this) { 108 needNewBuffer(size); 109 } 110 } 111 112 /** 113 * @see java.io.ByteArrayOutputStream#reset() 114 */ 115 @Override reset()116 public synchronized void reset() { 117 resetImpl(); 118 } 119 120 @Override size()121 public synchronized int size() { 122 return count; 123 } 124 125 @Override toByteArray()126 public synchronized byte[] toByteArray() { 127 return toByteArrayImpl(); 128 } 129 130 @Override toInputStream()131 public synchronized InputStream toInputStream() { 132 return toInputStream(java.io.ByteArrayInputStream::new); 133 } 134 135 @Override write(final byte[] b, final int off, final int len)136 public void write(final byte[] b, final int off, final int len) { 137 if (off < 0 138 || off > b.length 139 || len < 0 140 || off + len > b.length 141 || off + len < 0) { 142 throw new IndexOutOfBoundsException(); 143 } 144 if (len == 0) { 145 return; 146 } 147 synchronized (this) { 148 writeImpl(b, off, len); 149 } 150 } 151 152 @Override write(final InputStream in)153 public synchronized int write(final InputStream in) throws IOException { 154 return writeImpl(in); 155 } 156 157 @Override write(final int b)158 public synchronized void write(final int b) { 159 writeImpl(b); 160 } 161 162 @Override writeTo(final OutputStream out)163 public synchronized void writeTo(final OutputStream out) throws IOException { 164 writeToImpl(out); 165 } 166 } 167