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 * https://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 import org.apache.commons.io.IOUtils;
25
26 /**
27 * Implements a ThreadSafe version of {@link AbstractByteArrayOutputStream} using instance synchronization.
28 */
29 //@ThreadSafe
30 public class ByteArrayOutputStream extends AbstractByteArrayOutputStream<ByteArrayOutputStream> {
31
32 /**
33 * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream.
34 * <p>
35 * This method is useful where,
36 * </p>
37 * <ul>
38 * <li>Source InputStream is slow.</li>
39 * <li>It has network resources associated, so we cannot keep it open for long time.</li>
40 * <li>It has network timeout associated.</li>
41 * </ul>
42 * <p>
43 * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br>
44 * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
45 * </p>
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 */
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 same data as result InputStream.
59 * <p>
60 * This method is useful where,
61 * </p>
62 * <ul>
63 * <li>Source InputStream is slow.</li>
64 * <li>It has network resources associated, so we cannot keep it open for long time.</li>
65 * <li>It has network timeout associated.</li>
66 * </ul>
67 * <p>
68 * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br>
69 * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
70 * </p>
71 *
72 * @param input Stream to be fully buffered.
73 * @param size the initial buffer size.
74 * @return A fully buffered stream.
75 * @throws IOException if an I/O error occurs.
76 * @since 2.5
77 */
78 public static InputStream toBufferedInputStream(final InputStream input, final int size)
79 throws IOException {
80 try (ByteArrayOutputStream output = new ByteArrayOutputStream(size)) {
81 output.write(input);
82 return output.toInputStream();
83 }
84 }
85
86 /**
87 * Constructs a new byte array output stream. The buffer capacity is
88 * initially {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary.
89 */
90 public ByteArrayOutputStream() {
91 this(DEFAULT_SIZE);
92 }
93
94 /**
95 * Constructs a new byte array output stream, with a buffer capacity of
96 * the specified size, in bytes.
97 *
98 * @param size the initial size
99 * @throws IllegalArgumentException if size is negative
100 */
101 public ByteArrayOutputStream(final int size) {
102 if (size < 0) {
103 throw new IllegalArgumentException("Negative initial size: " + size);
104 }
105 synchronized (this) {
106 needNewBuffer(size);
107 }
108 }
109
110 /**
111 * @see java.io.ByteArrayOutputStream#reset()
112 */
113 @Override
114 public synchronized void reset() {
115 resetImpl();
116 }
117
118 @Override
119 public synchronized int size() {
120 return count;
121 }
122
123 @Override
124 public synchronized byte[] toByteArray() {
125 return toByteArrayImpl();
126 }
127
128 @Override
129 public synchronized InputStream toInputStream() {
130 return toInputStream(java.io.ByteArrayInputStream::new);
131 }
132
133 @Override
134 public void write(final byte[] b, final int off, final int len) {
135 IOUtils.checkFromIndexSize(b, off, len);
136 if (len == 0) {
137 return;
138 }
139 synchronized (this) {
140 writeImpl(b, off, len);
141 }
142 }
143
144 @Override
145 public synchronized int write(final InputStream in) throws IOException {
146 return writeImpl(in);
147 }
148
149 @Override
150 public synchronized void write(final int b) {
151 writeImpl(b);
152 }
153
154 @Override
155 public synchronized void writeTo(final OutputStream out) throws IOException {
156 writeToImpl(out);
157 }
158 }