Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/axis/utils/ByteArrayOutputStream.java


1   /*
2    * Copyright 2003,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.axis.utils;
18  
19  import java.io.IOException;
20  import java.io.OutputStream;
21  import java.io.UnsupportedEncodingException;
22  import java.util.List;
23  
24  /**
25   * This class implements an output stream in which the data is
26   * written into a byte array. The buffer automatically grows as data
27   * is written to it.
28   * <p/>
29   * The data can be retrieved using <code>toByteArray()</code> and
30   * <code>toString()</code>.
31   * <p/>
32   * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
33   * this class can be called after the stream has been closed without
34   * generating an <tt>IOException</tt>.
35   * <p/>
36   * This is an alternative implementation of the java.io.ByteArrayOutputStream
37   * class. The original implementation only allocates 32 bytes at the beginning.
38   * As this class is designed for heavy duty it starts at 1024 bytes. In contrast
39   * to the original it doesn't reallocate the whole memory block but allocates
40   * additional buffers. This way no buffers need to be garbage collected and
41   * the contents don't have to be copied to the new buffer. This class is
42   * designed to behave exactly like the original. The only exception is the
43   * deprecated toString(int) method that has been ignored.
44   *
45   * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
46   */
47  public class ByteArrayOutputStream extends OutputStream {
48  
49      private List buffers = new java.util.ArrayList();
50      private int currentBufferIndex;
51      private int filledBufferSum;
52      private byte[] currentBuffer;
53      private int count;
54  
55      /**
56       * Creates a new byte array output stream. The buffer capacity is
57       * initially 1024 bytes, though its size increases if necessary.
58       */
59      public ByteArrayOutputStream() {
60          this(1024);
61      }
62  
63      /**
64       * Creates a new byte array output stream, with a buffer capacity of
65       * the specified size, in bytes.
66       *
67       * @param size the initial size.
68       * @throws IllegalArgumentException if size is negative.
69       */
70      public ByteArrayOutputStream(int size) {
71          if (size < 0) {
72              throw new IllegalArgumentException(
73                      Messages.getMessage("illegalArgumentException01",
74                              Integer.toString(size)));
75          }
76          needNewBuffer(size);
77      }
78  
79      private byte[] getBuffer(int index) {
80          return (byte[]) buffers.get(index);
81      }
82  
83      private void needNewBuffer(int newcount) {
84          if (currentBufferIndex < buffers.size() - 1) {
85              //Recycling old buffer
86              filledBufferSum += currentBuffer.length;
87              currentBufferIndex++;
88              currentBuffer = getBuffer(currentBufferIndex);
89          } else {
90              //Creating new buffer
91              int newBufferSize;
92              if (currentBuffer == null) {
93                  newBufferSize = newcount;
94                  filledBufferSum = 0;
95              } else {
96                  newBufferSize = Math.max(currentBuffer.length << 1,
97                          newcount - filledBufferSum);
98                  filledBufferSum += currentBuffer.length;
99              }
100             currentBufferIndex++;
101             currentBuffer = new byte[newBufferSize];
102             buffers.add(currentBuffer);
103         }
104     }
105 
106     /**
107      * @see java.io.OutputStream#write(byte[], int, int)
108      */
109     public synchronized void write(byte[] b, int off, int len) {
110         if ((off < 0)
111                 || (off > b.length)
112                 || (len < 0)
113                 || ((off + len) > b.length)
114                 || ((off + len) < 0)) {
115             throw new IndexOutOfBoundsException(
116                     Messages.getMessage("indexOutOfBoundsException00"));
117         } else if (len == 0) {
118             return;
119         }
120         int newcount = count + len;
121         int remaining = len;
122         int inBufferPos = count - filledBufferSum;
123         while (remaining > 0) {
124             int part = Math.min(remaining, currentBuffer.length - inBufferPos);
125             System.arraycopy(b, off + len - remaining, currentBuffer,
126                     inBufferPos, part);
127             remaining -= part;
128             if (remaining > 0) {
129                 needNewBuffer(newcount);
130                 inBufferPos = 0;
131             }
132         }
133         count = newcount;
134     }
135 
136     /**
137      * Calls the write(byte[]) method.
138      *
139      * @see java.io.OutputStream#write(int)
140      */
141     public synchronized void write(int b) {
142         write(new byte[]{(byte) b}, 0, 1);
143     }
144 
145     /**
146      * @see java.io.ByteArrayOutputStream#size()
147      */
148     public int size() {
149         return count;
150     }
151 
152     /**
153      * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
154      * this class can be called after the stream has been closed without
155      * generating an <tt>IOException</tt>.
156      *
157      * @throws IOException in case an I/O error occurs
158      */
159     public void close() throws IOException {
160         //nop
161     }
162 
163     /**
164      * @see java.io.ByteArrayOutputStream#reset()
165      */
166     public synchronized void reset() {
167         count = 0;
168         filledBufferSum = 0;
169         currentBufferIndex = 0;
170         currentBuffer = getBuffer(currentBufferIndex);
171     }
172 
173     /**
174      * @see java.io.ByteArrayOutputStream#writeTo(OutputStream)
175      */
176     public synchronized void writeTo(OutputStream out) throws IOException {
177         int remaining = count;
178         for (int i = 0; i < buffers.size(); i++) {
179             byte[] buf = getBuffer(i);
180             int c = Math.min(buf.length, remaining);
181             out.write(buf, 0, c);
182             remaining -= c;
183             if (remaining == 0) {
184                 break;
185             }
186         }
187     }
188 
189     /**
190      * @see java.io.ByteArrayOutputStream#toByteArray()
191      */
192     public synchronized byte toByteArray()[] {
193         int remaining = count;
194         int pos = 0;
195         byte newbuf[] = new byte[count];
196         for (int i = 0; i < buffers.size(); i++) {
197             byte[] buf = getBuffer(i);
198             int c = Math.min(buf.length, remaining);
199             System.arraycopy(buf, 0, newbuf, pos, c);
200             pos += c;
201             remaining -= c;
202             if (remaining == 0) {
203                 break;
204             }
205         }
206         return newbuf;
207     }
208 
209     /**
210      * @see java.io.ByteArrayOutputStream#toString()
211      */
212     public String toString() {
213         return new String(toByteArray());
214     }
215 
216     /**
217      * @see java.io.ByteArrayOutputStream#toString(String)
218      */
219     public String toString(String enc) throws UnsupportedEncodingException {
220         return new String(toByteArray(), enc);
221     }
222 
223 }