Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package org.apache.catalina.tribes.io;
 
The XByteBuffer provides a dual functionality. One, it stores message bytes and automatically extends the byte buffer if needed.
Two, it can encode and decode packages so that they can be defined and identified as they come in on a socket.
THIS CLASS IS NOT THREAD SAFE

Transfer package:
  • START_DATA/b> - 7 bytes - FLT2002
  • SIZE - 4 bytes - size of the data package
  • DATA - should be as many bytes as the prev SIZE
  • END_DATA - 7 bytes - TLF2003
 
 public class XByteBuffer
 {
 
     private static final org.apache.juli.logging.Log log =
         org.apache.juli.logging.LogFactory.getLogXByteBuffer.class );

    
This is a package header, 7 bytes (FLT2002)
 
     private static final byte[] START_DATA = {70,76,84,50,48,48,50};

    
This is the package footer, 7 bytes (TLF2003)
 
     private static final byte[] END_DATA = {84,76,70,50,48,48,51};

    
Variable to hold the data
 
     protected byte[] buf = null;

    
Current length of data in the buffer
 
     protected int bufSize = 0;

    
Flag for discarding invalid packages If this flag is set to true, and append(byte[],...) is called, the data added will be inspected, and if it doesn't start with START_DATA it will be thrown away.
 
     protected boolean discard = true;

    
Constructs a new XByteBuffer.
TODO use a pool of byte[] for performance

Parameters:
size - the initial size of the byte buffer
 
     public XByteBuffer(int sizeboolean discard) {
          = new byte[size];
         this. = discard;
     }
 
     public XByteBuffer(byte[] data,boolean discard) {
         this(data,data.length+128,discard);
     }
 
     public XByteBuffer(byte[] dataint size,boolean discard) {
         int length = Math.max(data.length,size);
          = new byte[length];
         System.arraycopy(data,0,,0,data.length);
          = data.length;
        this. = discard;
    }
    public int getLength() {
        return ;
    }
    public void setLength(int size) {
        if ( size > . ) throw new ArrayIndexOutOfBoundsException("Size is larger than existing buffer.");
         = size;
    }
    public void trim(int length) {
        if ( ( - length) < 0 )
            throw new ArrayIndexOutOfBoundsException("Can't trim more bytes than are available. length:"++" trim:"+length);
         -= length;
    }
    public void reset() {
         = 0;
    }
    public byte[] getBytesDirect() {
        return this.;
    }

    
Returns the bytes in the buffer, in its exact length
    public byte[] getBytes() {
        byte[] b = new byte[];
        System.arraycopy(,0,b,0,);
        return b;
    }

    
Resets the buffer
    public void clear() {
         = 0;
    }

    
Appends the data to the buffer. If the data is incorrectly formatted, ie, the data should always start with the header, false will be returned and the data will be discarded.

Parameters:
b - bytes to be appended
len - the number of bytes to append.
Returns:
true if the data was appended correctly. Returns false if the package is incorrect, ie missing header or something, or the length of data is 0
    public boolean append(ByteBuffer bint len) {
        int newcount =  + len;
        if (newcount > .) {
            expand(newcount);
        }
        b.get(,,len);
         = newcount;
        if (  ) {
            if ( > . && (firstIndexOf(, 0, ) == -1)) {
                 = 0;
                .error("Discarded the package, invalid header");
                return false;
            }
        }
        return true;
    }
    public boolean append(byte i) {
        int newcount =  + 1;
        if (newcount > .) {
            expand(newcount);
        }
        [] = i;
         = newcount;
        return true;
    }
    public boolean append(boolean i) {
        int newcount =  + 1;
        if (newcount > .) {
            expand(newcount);
        }
        XByteBuffer.toBytes(i,,);
         = newcount;
        return true;
    }
    public boolean append(long i) {
        int newcount =  + 8;
        if (newcount > .) {
            expand(newcount);
        }
        XByteBuffer.toBytes(i,,);
         = newcount;
        return true;
    }
    public boolean append(int i) {
        int newcount =  + 4;
        if (newcount > .) {
            expand(newcount);
        }
        XByteBuffer.toBytes(i,,);
         = newcount;
        return true;
    }
    public boolean append(byte[] bint offint len) {
        if ((off < 0) || (off > b.length) || (len < 0) ||
            ((off + len) > b.length) || ((off + len) < 0))  {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return false;
        }
        int newcount =  + len;
        if (newcount > .) {
            expand(newcount);
        }
        System.arraycopy(bofflen);
         = newcount;
        if (  ) {
            if ( > . && (firstIndexOf(, 0, ) == -1)) {
                 = 0;
                .error("Discarded the package, invalid header");
                return false;
            }
        }
        return true;
    }
    public void expand(int newcount) {
        //don't change the allocation strategy
        byte newbuf[] = new byte[Math.max(. << 1, newcount)];
        System.arraycopy(, 0, newbuf, 0, );
         = newbuf;
    }
    public int getCapacity() {
        return .;
    }


    
Internal mechanism to make a check if a complete package exists within the buffer

Returns:
- true if a complete package (header,compress,size,data,footer) exists within the buffer
    public int countPackages() {
        return countPackages(false);
    }
    public int countPackages(boolean first)
    {
        int cnt = 0;
        int pos = .;
        int start = 0;
        while ( start <  ) {
            //first check start header
            int index = XByteBuffer.firstIndexOf(,start,);
            //if the header (START_DATA) isn't the first thing or
            //the buffer isn't even 14 bytes
            if ( index != start || ((-start)<14) ) break;
            //next 4 bytes are compress flag not needed for count packages
            //then get the size 4 bytes
            int size = toInt(pos);
            //now the total buffer has to be long enough to hold
            //START_DATA.length+4+size+END_DATA.length
            pos = start + . + 4 + size;
            if ( (pos + .) > break;
            //and finally check the footer of the package END_DATA
            int newpos = firstIndexOf(pos);
            //mismatch, there is no package
            if (newpos != posbreak;
            //increase the packet count
            cnt++;
            //reset the values
            start = pos + .;
            pos = start + .;
            //we only want to verify that we have at least one package
            if ( first ) break;
        }
        return cnt;
    }

    
Method to check if a package exists in this byte buffer.

Returns:
- true if a complete package (header,options,size,data,footer) exists within the buffer
    public boolean doesPackageExist()  {
        return (countPackages(true)>0);
    }

    
Extracts the message bytes from a package. If no package exists, a IllegalStateException will be thrown.

Parameters:
clearFromBuffer - if true, the package will be removed from the byte buffer
Returns:
- returns the actual message bytes (header, compress,size and footer not included).
    public XByteBuffer extractDataPackage(boolean clearFromBuffer) {
        int psize = countPackages(true);
        if (psize == 0) {
            throw new java.lang.IllegalStateException("No package exists in XByteBuffer");
        }
        int size = toInt(.);
        XByteBuffer xbuf = BufferPool.getBufferPool().getBuffer(size,false);
        xbuf.setLength(size);
        System.arraycopy(. + 4, xbuf.getBytesDirect(), 0, size);
        if (clearFromBuffer) {
            int totalsize = . + 4 + size + .;
             =  - totalsize;
            System.arraycopy(totalsize, 0, );
        }
        return xbuf;
    }
    public ChannelData extractPackage(boolean clearFromBuffer) {
        XByteBuffer xbuf = extractDataPackage(clearFromBuffer);
        ChannelData cdata = ChannelData.getDataFromPackage(xbuf);
        return cdata;
    }

    
Creates a complete data package

Parameters:
cdata - the message data to be contained within the package
Returns:
- a full package (header,size,data,footer)
    public static byte[] createDataPackage(ChannelData cdata) {
//        return createDataPackage(cdata.getDataPackage());
        //avoid one extra byte array creation
        int dlength = cdata.getDataPackageLength();
        int length = getDataPackageLength(dlength);
        byte[] data = new byte[length];
        int offset = 0;
        System.arraycopy(, 0, dataoffset.);
        offset += .;
        toBytes(dlength,data.);
        offset += 4;
        cdata.getDataPackage(data,offset);
        offset += dlength;
        System.arraycopy(, 0, dataoffset.);
        offset += .;
        return data;
    }
    public static byte[] createDataPackage(byte[] dataint doffint dlengthbyte[] bufferint bufoff) {
        if ( (buffer.length-bufoff) > getDataPackageLength(dlength) ) {
            throw new ArrayIndexOutOfBoundsException("Unable to create data package, buffer is too small.");
        }
        System.arraycopy(, 0, bufferbufoff.);
        toBytes(data.length,bufferbufoff+.);
        System.arraycopy(datadoffbufferbufoff+. + 4, dlength);
        System.arraycopy(, 0, bufferbufoff+. + 4 + data.length.);
        return buffer;
    }
    public static int getDataPackageLength(int datalength) {
        int length =
            . + //header length
            4 + //data length indicator
            datalength + //actual data length
            .//footer length
        return length;
    }
    public static byte[] createDataPackage(byte[] data) {
        int length = getDataPackageLength(data.length);
        byte[] result = new byte[length];
        return createDataPackage(data,0,data.length,result,0);
    }
//    public static void fillDataPackage(byte[] data, int doff, int dlength, XByteBuffer buf) {
//        int pkglen = getDataPackageLength(dlength);
//        if ( buf.getCapacity() <  pkglen ) buf.expand(pkglen);
//        createDataPackage(data,doff,dlength,buf.getBytesDirect(),buf.getLength());
//    }

    
Convert four bytes to an int

Parameters:
b - the byte array containing the four bytes
off - the offset
Returns:
the integer value constructed from the four bytes
Throws:
java.lang.ArrayIndexOutOfBoundsException
    public static int toInt(byte[] b,int off){
        return ( ( b[off+3]) & 0xFF) +
            ( ( ( b[off+2]) & 0xFF) << 8) +
            ( ( ( b[off+1]) & 0xFF) << 16) +
            ( ( ( b[off+0]) & 0xFF) << 24);
    }

    
Convert eight bytes to a long

Parameters:
b - the byte array containing the four bytes
off - the offset
Returns:
the long value constructed from the eight bytes
Throws:
java.lang.ArrayIndexOutOfBoundsException
    public static long toLong(byte[] b,int off){
        return ( ( (longb[off+7]) & 0xFF) +
            ( ( ( (longb[off+6]) & 0xFF) << 8) +
            ( ( ( (longb[off+5]) & 0xFF) << 16) +
            ( ( ( (longb[off+4]) & 0xFF) << 24) +
            ( ( ( (longb[off+3]) & 0xFF) << 32) +
            ( ( ( (longb[off+2]) & 0xFF) << 40) +
            ( ( ( (longb[off+1]) & 0xFF) << 48) +
            ( ( ( (longb[off+0]) & 0xFF) << 56);
    }


    
Converts a boolean to a 1-byte array

Parameters:
bool - the integer
Returns:
- 1-byte array
    public static byte[] toBytes(boolean boolbyte[] dataint offset) {
        data[offset] = (byte)(bool?1:0);
        return data;
    }

    
Converts a byte array entry to boolean

Parameters:
b byte array
offset within byte array
Returns:
true if byte array entry is non-zero, false otherwise
    public static boolean toBoolean(byte[] bint offset) {
        return b[offset] != 0;
    }


    
Converts an integer to four bytes

Parameters:
n - the integer
Returns:
- four bytes in an array
    public static byte[] toBytes(int n,byte[] bint offset) {
        b[offset+3] = (byte) (n);
        n >>>= 8;
        b[offset+2] = (byte) (n);
        n >>>= 8;
        b[offset+1] = (byte) (n);
        n >>>= 8;
        b[offset+0] = (byte) (n);
        return b;
    }

    
Converts an long to eight bytes

Parameters:
n - the long
Returns:
- eight bytes in an array
    public static byte[] toBytes(long nbyte[] bint offset) {
        b[offset+7] = (byte) (n);
        n >>>= 8;
        b[offset+6] = (byte) (n);
        n >>>= 8;
        b[offset+5] = (byte) (n);
        n >>>= 8;
        b[offset+4] = (byte) (n);
        n >>>= 8;
        b[offset+3] = (byte) (n);
        n >>>= 8;
        b[offset+2] = (byte) (n);
        n >>>= 8;
        b[offset+1] = (byte) (n);
        n >>>= 8;
        b[offset+0] = (byte) (n);
        return b;
    }

    
Similar to a String.IndexOf, but uses pure bytes

Parameters:
src - the source bytes to be searched
srcOff - offset on the source buffer
find - the string to be found within src
Returns:
- the index of the first matching byte. -1 if the find array is not found
    public static int firstIndexOf(byte[] srcint srcOffbyte[] find){
        int result = -1;
        if (find.length > src.lengthreturn result;
        if (find.length == 0 || src.length == 0) return result;
        if (srcOff >= src.length ) throw new java.lang.ArrayIndexOutOfBoundsException();
        boolean found = false;
        int srclen = src.length;
        int findlen = find.length;
        byte first = find[0];
        int pos = srcOff;
        while (!found) {
            //find the first byte
            while (pos < srclen){
                if (first == src[pos])
                    break;
                pos++;
            }
            if (pos >= srclen)
                return -1;
            //we found the first character
            //match the rest of the bytes - they have to match
            if ( (srclen - pos) < findlen)
                return -1;
            //assume it does exist
            found = true;
            for (int i = 1; ( (i < findlen) && found); i++)
                found = found && (find[i] == src[pos + i]);
            if (found)
                result = pos;
            else if ( (srclen - pos) < findlen)
                return -1; //no more matches possible
            else
                pos++;
        }
        return result;
    }
    public static Serializable deserialize(byte[] data)
        return deserialize(data,0,data.length);
    }
    public static Serializable deserialize(byte[] dataint offsetint length)
        return deserialize(data,offset,length,null);
    }
    private static final AtomicInteger invokecount = new AtomicInteger(0);
    public static Serializable deserialize(byte[] dataint offsetint lengthClassLoader[] cls)
        .addAndGet(1);
        Object message = null;
        if ( cls == null ) cls = new ClassLoader[0];
        if (data != null && length > 0) {
            InputStream  instream = new ByteArrayInputStream(data,offset,length);
            ObjectInputStream stream = null;
            stream = (cls.length>0)? new ReplicationStream(instream,cls):new ObjectInputStream(instream);
            message = stream.readObject();
            instream.close();
            stream.close();
        }
        if ( message == null ) {
            return null;
        } else if (message instanceof Serializable)
            return (Serializablemessage;
        else {
            throw new ClassCastException("Message has the wrong class. It should implement Serializable, instead it is:"+message.getClass().getName());
        }
    }

    
Serializes a message into cluster data

Parameters:
msg ClusterMessage
Returns:
serialized content as byte[] array
Throws:
java.io.IOException
    public static byte[] serialize(Serializable msgthrows IOException {
        ByteArrayOutputStream outs = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(outs);
        out.writeObject(msg);
        out.flush();
        byte[] data = outs.toByteArray();
        return data;
    }
    public void setDiscard(boolean discard) {
        this. = discard;
    }
    public boolean getDiscard() {
        return ;
    }
New to GrepCode? Check out our FAQ X