001    /** 
002     * 
003     * Copyright 2004 Protique Ltd
004     * 
005     * Licensed under the Apache License, Version 2.0 (the "License"); 
006     * you may not use this file except in compliance with the License. 
007     * 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     * 
017     **/
018    
019    package org.activemq.io.util;
020    import java.io.ByteArrayInputStream;
021    
022    /**
023     * Optimized ByteArrayInputStream that can be used more than once. Which is nice.
024     * 
025     * @version $Revision: 1.1.1.1 $
026     */
027    public class WireByteArrayInputStream extends ByteArrayInputStream {
028        /**
029         * Creates a <code>WireByteArrayInputStream</code>.
030         * 
031         * @param buf the input buffer.
032         */
033        public WireByteArrayInputStream(byte buf[]) {
034            super(buf);
035        }
036    
037        /**
038         * Creates <code>WireByteArrayInputStream</code> that uses <code>buf</code> as its buffer array.
039         * 
040         * @param buf the input buffer.
041         * @param offset the offset in the buffer of the first byte to read.
042         * @param length the maximum number of bytes to read from the buffer.
043         */
044        public WireByteArrayInputStream(byte buf[], int offset, int length) {
045            super(buf, offset, length);
046        }
047        
048        /**
049         * Create a <code>WireByteArrayInputStream</code> that uses a <code>ByteArray</code>
050         * @param ba
051         */
052        public WireByteArrayInputStream(ByteArray ba){
053            super(ba.getBuf(),ba.getOffset(),ba.getLength());
054        }
055    
056        /**
057         * Creates <code>WireByteArrayInputStream</code> with a minmalist byte array
058         */
059        public WireByteArrayInputStream() {
060            super(new byte[0]);
061        }
062        
063        /**
064         * @return the current position in the stream
065         */
066        public int position(){
067            return pos;
068        }
069        
070        /**
071         * @return the underlying data array
072         */
073        public byte[] getRawData(){
074            return buf;
075        }
076    
077        /**
078         * reset the <code>WireByteArrayInputStream</code> to use an new byte array
079         * 
080         * @param newBuff buffer to use
081         * @param offset the offset in the buffer of the first byte to read.
082         * @param length the maximum number of bytes to read from the buffer.
083         */
084        public void restart(byte[] newBuff, int offset, int length) {
085            buf = newBuff;
086            pos = offset;
087            count = Math.min(offset + length, newBuff.length);
088            mark = offset;
089        }
090    
091        /**
092         * reset the <code>WireByteArrayInputStream</code> to use an new byte array
093         * 
094         * @param newBuff
095         */
096        public void restart(byte[] newBuff) {
097            restart(newBuff, 0, newBuff.length);
098        }
099    
100        /**
101         * Reads the next byte of data from this input stream. The value byte is returned as an <code>int</code> in the
102         * range <code>0</code> to <code>255</code>. If no byte is available because the end of the stream has been
103         * reached, the value <code>-1</code> is returned.
104         * <p>
105         * This <code>read</code> method cannot block.
106         * 
107         * @return the next byte of data, or <code>-1</code> if the end of the stream has been reached.
108         */
109        public int read() {
110            return (pos < count) ? (buf[pos++] & 0xff) : -1;
111        }
112    
113        /**
114         * Reads up to <code>len</code> bytes of data into an array of bytes from this input stream.
115         * 
116         * @param b the buffer into which the data is read.
117         * @param off the start offset of the data.
118         * @param len the maximum number of bytes read.
119         * @return the total number of bytes read into the buffer, or <code>-1</code> if there is no more data because the
120         * end of the stream has been reached.
121         */
122        public int read(byte b[], int off, int len) {
123            if (b == null) {
124                throw new NullPointerException();
125            }
126            else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) {
127                throw new IndexOutOfBoundsException();
128            }
129            if (pos >= count) {
130                return -1;
131            }
132            if (pos + len > count) {
133                len = count - pos;
134            }
135            if (len <= 0) {
136                return 0;
137            }
138            System.arraycopy(buf, pos, b, off, len);
139            pos += len;
140            return len;
141        }
142    
143        /**
144         * @return the number of bytes that can be read from the input stream without blocking.
145         */
146        public int available() {
147            return count - pos;
148        }
149    }