001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.io.output; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.io.OutputStream; 022 023/** 024 * Implements a ThreadSafe version of {@link AbstractByteArrayOutputStream} using instance synchronization. 025 */ 026//@ThreadSafe 027public class ByteArrayOutputStream extends AbstractByteArrayOutputStream { 028 029 /** 030 * Creates a new byte array output stream. The buffer capacity is 031 * initially {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary. 032 */ 033 public ByteArrayOutputStream() { 034 this(DEFAULT_SIZE); 035 } 036 037 /** 038 * Creates a new byte array output stream, with a buffer capacity of 039 * the specified size, in bytes. 040 * 041 * @param size the initial size 042 * @throws IllegalArgumentException if size is negative 043 */ 044 public ByteArrayOutputStream(final int size) { 045 if (size < 0) { 046 throw new IllegalArgumentException( 047 "Negative initial size: " + size); 048 } 049 synchronized (this) { 050 needNewBuffer(size); 051 } 052 } 053 054 @Override 055 public void write(final byte[] b, final int off, final int len) { 056 if ((off < 0) 057 || (off > b.length) 058 || (len < 0) 059 || ((off + len) > b.length) 060 || ((off + len) < 0)) { 061 throw new IndexOutOfBoundsException(); 062 } 063 if (len == 0) { 064 return; 065 } 066 synchronized (this) { 067 writeImpl(b, off, len); 068 } 069 } 070 071 @Override 072 public synchronized void write(final int b) { 073 writeImpl(b); 074 } 075 076 @Override 077 public synchronized int write(final InputStream in) throws IOException { 078 return writeImpl(in); 079 } 080 081 @Override 082 public synchronized int size() { 083 return count; 084 } 085 086 /** 087 * @see java.io.ByteArrayOutputStream#reset() 088 */ 089 @Override 090 public synchronized void reset() { 091 resetImpl(); 092 } 093 094 @Override 095 public synchronized void writeTo(final OutputStream out) throws IOException { 096 writeToImpl(out); 097 } 098 099 /** 100 * Fetches entire contents of an {@code InputStream} and represent 101 * same data as result InputStream. 102 * <p> 103 * This method is useful where, 104 * </p> 105 * <ul> 106 * <li>Source InputStream is slow.</li> 107 * <li>It has network resources associated, so we cannot keep it open for 108 * long time.</li> 109 * <li>It has network timeout associated.</li> 110 * </ul> 111 * It can be used in favor of {@link #toByteArray()}, since it 112 * avoids unnecessary allocation and copy of byte[].<br> 113 * This method buffers the input internally, so there is no need to use a 114 * {@code BufferedInputStream}. 115 * 116 * @param input Stream to be fully buffered. 117 * @return A fully buffered stream. 118 * @throws IOException if an I/O error occurs. 119 * @since 2.0 120 */ 121 public static InputStream toBufferedInputStream(final InputStream input) 122 throws IOException { 123 return toBufferedInputStream(input, DEFAULT_SIZE); 124 } 125 126 /** 127 * Fetches entire contents of an {@code InputStream} and represent 128 * same data as result InputStream. 129 * <p> 130 * This method is useful where, 131 * </p> 132 * <ul> 133 * <li>Source InputStream is slow.</li> 134 * <li>It has network resources associated, so we cannot keep it open for 135 * long time.</li> 136 * <li>It has network timeout associated.</li> 137 * </ul> 138 * It can be used in favor of {@link #toByteArray()}, since it 139 * avoids unnecessary allocation and copy of byte[].<br> 140 * This method buffers the input internally, so there is no need to use a 141 * {@code BufferedInputStream}. 142 * 143 * @param input Stream to be fully buffered. 144 * @param size the initial buffer size 145 * @return A fully buffered stream. 146 * @throws IOException if an I/O error occurs. 147 * @since 2.5 148 */ 149 public static InputStream toBufferedInputStream(final InputStream input, final int size) 150 throws IOException { 151 try (final ByteArrayOutputStream output = new ByteArrayOutputStream(size)) { 152 output.write(input); 153 return output.toInputStream(); 154 } 155 } 156 157 @Override 158 public synchronized InputStream toInputStream() { 159 return toInputStream(java.io.ByteArrayInputStream::new); 160 } 161 162 @Override 163 public synchronized byte[] toByteArray() { 164 return toByteArrayImpl(); 165 } 166}