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