001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.util;
038:
039: import java.io.ByteArrayInputStream;
040: import java.io.ByteArrayOutputStream;
041: import java.io.IOException;
042: import java.io.InputStream;
043: import java.io.OutputStream;
044:
045: /**
046: * Read/write buffer that stores a sequence of bytes.
047: *
048: * <p>
049: * It works in a way similar to {@link ByteArrayOutputStream} but
050: * this class works better in the following ways:
051: *
052: * <ol>
053: * <li>no synchronization
054: * <li>offers a {@link #newInputStream()} that creates a new {@link InputStream}
055: * that won't cause buffer reallocation.
056: * <li>less parameter correctness checking
057: * <li>offers a {@link #write(InputStream)} method that reads the entirety of the
058: * given {@link InputStream} without using a temporary buffer.
059: * </ol>
060: *
061: * @author Kohsuke Kawaguchi
062: */
063: public class ByteArrayBuffer extends OutputStream {
064: /**
065: * The buffer where data is stored.
066: */
067: protected byte[] buf;
068:
069: /**
070: * The number of valid bytes in the buffer.
071: */
072: private int count;
073:
074: /**
075: * Creates a new byte array output stream. The buffer capacity is
076: * initially 32 bytes, though its size increases if necessary.
077: */
078: public ByteArrayBuffer() {
079: this (32);
080: }
081:
082: /**
083: * Creates a new byte array output stream, with a buffer capacity of
084: * the specified size, in bytes.
085: *
086: * @param size the initial size.
087: * @throws IllegalArgumentException if size is negative.
088: */
089: public ByteArrayBuffer(int size) {
090: if (size <= 0)
091: throw new IllegalArgumentException();
092: buf = new byte[size];
093: }
094:
095: public ByteArrayBuffer(byte[] data) {
096: this .buf = data;
097: }
098:
099: /**
100: * Reads all the data of the given {@link InputStream} and appends them
101: * into this buffer.
102: *
103: * @throws IOException
104: * if the read operation fails with an {@link IOException}.
105: */
106: public final void write(InputStream in) throws IOException {
107: while (true) {
108: int cap = buf.length - count; // the remaining buffer space
109: int sz = in.read(buf, count, cap);
110: if (sz < 0)
111: return; // hit EOS
112: count += sz;
113:
114: if (cap == sz)
115: ensureCapacity(buf.length * 2); // buffer filled up.
116: }
117: }
118:
119: public final void write(int b) {
120: int newcount = count + 1;
121: ensureCapacity(newcount);
122: buf[count] = (byte) b;
123: count = newcount;
124: }
125:
126: public final void write(byte b[], int off, int len) {
127: int newcount = count + len;
128: ensureCapacity(newcount);
129: System.arraycopy(b, off, buf, count, len);
130: count = newcount;
131: }
132:
133: private void ensureCapacity(int newcount) {
134: if (newcount > buf.length) {
135: byte newbuf[] = new byte[Math
136: .max(buf.length << 1, newcount)];
137: System.arraycopy(buf, 0, newbuf, 0, count);
138: buf = newbuf;
139: }
140: }
141:
142: public final void writeTo(OutputStream out) throws IOException {
143: out.write(buf, 0, count);
144: }
145:
146: public final void reset() {
147: count = 0;
148: }
149:
150: /**
151: * Gets the <b>copy</b> of exact-size byte[] that represents the written data.
152: *
153: * <p>
154: * Since this method needs to allocate a new byte[], this method will be costly.
155: *
156: * @deprecated
157: * this method causes a buffer reallocation. Use it only when
158: * you have to.
159: */
160: public final byte[] toByteArray() {
161: byte newbuf[] = new byte[count];
162: System.arraycopy(buf, 0, newbuf, 0, count);
163: return newbuf;
164: }
165:
166: public final int size() {
167: return count;
168: }
169:
170: /**
171: * Gets the underlying buffer that this {@link ByteArrayBuffer} uses.
172: * It's never small than its {@link #size()}.
173: *
174: * Use with caution.
175: */
176: public final byte[] getRawData() {
177: return buf;
178: }
179:
180: public void close() throws IOException {
181: }
182:
183: /**
184: * Creates a new {@link InputStream} that reads from this buffer.
185: */
186: public final InputStream newInputStream() {
187: return new ByteArrayInputStream(buf, 0, count);
188: }
189:
190: /**
191: * Creates a new {@link InputStream} that reads a part of this bfufer.
192: */
193: public final InputStream newInputStream(int start, int length) {
194: return new ByteArrayInputStream(buf, start, length);
195: }
196:
197: /**
198: * Decodes the contents of this buffer by the default encoding
199: * and returns it as a string.
200: *
201: * <p>
202: * Meant to aid debugging, but no more.
203: */
204: public String toString() {
205: return new String(buf, 0, count);
206: }
207: }
|