Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/io/XByteBuffer.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/io/XByteBuffer.java?view=diff&rev=467173&r1=467172&r2=467173
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/io/XByteBuffer.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/io/XByteBuffer.java 
Mon Oct 23 16:12:17 2006
@@ -1,612 +1,612 @@
-/*
- * 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;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.nio.ByteBuffer;
-
-/**
- * The XByteBuffer provides a dual functionality.
- * One, it stores message bytes and automatically extends the byte buffer if 
needed.<BR>
- * Two, it can encode and decode packages so that they can be defined and 
identified
- * as they come in on a socket.
- * <br>
- * <b>THIS CLASS IS NOT THREAD SAFE</B><BR>
- * <br/>
- * Transfer package:
- * <ul>
- * <li><b>START_DATA/b> - 7 bytes - <i>FLT2002</i></li>
- * <li><b>SIZE</b>      - 4 bytes - size of the data package</li>
- * <li><b>DATA</b>      - should be as many bytes as the prev SIZE</li>
- * <li><b>END_DATA</b>  - 7 bytes - <i>TLF2003</i></lI>
- * </ul>
- * @author Filip Hanik
- * @version $Revision: 377484 $, $Date: 2006-02-13 15:00:05 -0600 (Mon, 13 Feb 
2006) $
- */
-public class XByteBuffer
-{
-    
-    public static org.apache.juli.logging.Log log =
-        org.apache.juli.logging.LogFactory.getLog( XByteBuffer.class );
-    
-    /**
-     * This is a package header, 7 bytes (FLT2002)
-     */
-    public static final byte[] START_DATA = {70,76,84,50,48,48,50};
-    
-    /**
-     * This is the package footer, 7 bytes (TLF2003)
-     */
-    public static final byte[] END_DATA = {84,76,70,50,48,48,51};
- 
-    /**
-     * Default size on the initial byte buffer
-     */
-    private static final int DEF_SIZE = 2048;
- 
-    /**
-     * Default size to extend the buffer with
-     */
-    private static final int DEF_EXT  = 1024;
-    
-    /**
-     * 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 
-     * <code>START_DATA</code> it will be thrown away.
-     * 
-     */
-    protected boolean discard = true;
-    
-    /**
-     * Constructs a new XByteBuffer
-     * @param size - the initial size of the byte buffer
-     * @todo use a pool of byte[] for performance
-     */
-    public XByteBuffer(int size, boolean discard) {
-        buf = new byte[size];
-        this.discard = discard;
-    }
-    
-    public XByteBuffer(byte[] data,boolean discard) {
-        this(data,data.length+128,discard);
-    }
-    
-    public XByteBuffer(byte[] data, int size,boolean discard) {
-        int length = Math.max(data.length,size);
-        buf = new byte[length];
-        System.arraycopy(data,0,buf,0,data.length);
-        bufSize = data.length;
-        this.discard = discard;
-    }
-    
-    public int getLength() {
-        return bufSize;
-    }
-
-    public void setLength(int size) {
-        if ( size > buf.length ) throw new 
ArrayIndexOutOfBoundsException("Size is larger than existing buffer.");
-        bufSize = size;
-    }
-    
-    public void trim(int length) {
-        if ( (bufSize - length) < 0 ) 
-            throw new ArrayIndexOutOfBoundsException("Can't trim more bytes 
than are available. length:"+bufSize+" trim:"+length);
-        bufSize -= length;
-    }
-    
-    public void reset() {
-        bufSize = 0;
-    }
-            
-    public byte[] getBytesDirect() {
-        return this.buf;
-    }
-
-    /**
-     * Returns the bytes in the buffer, in its exact length
-     */
-    public byte[] getBytes() {
-        byte[] b = new byte[bufSize];
-        System.arraycopy(buf,0,b,0,bufSize);
-        return b;
-    }
-
-    /**
-     * Resets the buffer
-     */
-    public void clear() {
-        bufSize = 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.
-     * @param b - bytes to be appended
-     * @param off - the offset to extract data from
-     * @param len - the number of bytes to append.
-     * @return 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 b, int len) {
-        int newcount = bufSize + len;
-        if (newcount > buf.length) {
-            expand(newcount);
-        }
-        b.get(buf,bufSize,len);
-        
-        bufSize = newcount;
-        
-        if ( discard ) {
-            if (bufSize > START_DATA.length && (firstIndexOf(buf, 0, 
START_DATA) == -1)) {
-                bufSize = 0;
-                log.error("Discarded the package, invalid header");
-                return false;
-            }
-        }
-        return true;
-
-    }
-    
-    public boolean append(byte i) {
-        int newcount = bufSize + 1;
-        if (newcount > buf.length) {
-            expand(newcount);
-        }
-        buf[bufSize] = i;
-        bufSize = newcount;
-        return true;
-    }
-
-
-    public boolean append(boolean i) {
-        int newcount = bufSize + 1;
-        if (newcount > buf.length) {
-            expand(newcount);
-        }
-        XByteBuffer.toBytes(i,buf,bufSize);
-        bufSize = newcount;
-        return true;
-    }
-
-    public boolean append(long i) {
-        int newcount = bufSize + 8;
-        if (newcount > buf.length) {
-            expand(newcount);
-        }
-        XByteBuffer.toBytes(i,buf,bufSize);
-        bufSize = newcount;
-        return true;
-    }
-    
-    public boolean append(int i) {
-        int newcount = bufSize + 4;
-        if (newcount > buf.length) {
-            expand(newcount);
-        }
-        XByteBuffer.toBytes(i,buf,bufSize);
-        bufSize = newcount;
-        return true;
-    }
-
-    public boolean append(byte[] b, int off, int 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 = bufSize + len;
-        if (newcount > buf.length) {
-            expand(newcount);
-        }
-        System.arraycopy(b, off, buf, bufSize, len);
-        bufSize = newcount;
-
-        if ( discard ) {
-            if (bufSize > START_DATA.length && (firstIndexOf(buf, 0, 
START_DATA) == -1)) {
-                bufSize = 0;
-                log.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(buf.length << 1, newcount)];
-        System.arraycopy(buf, 0, newbuf, 0, bufSize);
-        buf = newbuf;
-    }
-    
-    public int getCapacity() {
-        return buf.length;
-    }
-
-
-    /**
-     * Internal mechanism to make a check if a complete package exists
-     * within the buffer
-     * @return - 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 = START_DATA.length;
-        int start = 0;
-
-        while ( start < bufSize ) {
-            //first check start header
-            int index = XByteBuffer.firstIndexOf(buf,start,START_DATA);
-            //if the header (START_DATA) isn't the first thing or
-            //the buffer isn't even 14 bytes
-            if ( index != start || ((bufSize-start)<14) ) break;
-            //next 4 bytes are compress flag not needed for count packages
-            //then get the size 4 bytes
-            int size = toInt(buf, pos);
-            //now the total buffer has to be long enough to hold
-            //START_DATA.length+4+size+END_DATA.length
-            pos = start + START_DATA.length + 4 + size;
-            if ( (pos + END_DATA.length) > bufSize) break;
-            //and finally check the footer of the package END_DATA
-            int newpos = firstIndexOf(buf, pos, END_DATA);
-            //mismatch, there is no package
-            if (newpos != pos) break;
-            //increase the packet count
-            cnt++;
-            //reset the values
-            start = pos + END_DATA.length;
-            pos = start + START_DATA.length;
-            //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.
-     * @return - 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.
-     * @param clearFromBuffer - if true, the package will be removed from the 
byte buffer
-     * @return - 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(buf, START_DATA.length);
-        XByteBuffer xbuf = BufferPool.getBufferPool().getBuffer(size,false);
-        xbuf.setLength(size);
-        System.arraycopy(buf, START_DATA.length + 4, xbuf.getBytesDirect(), 0, 
size);
-        if (clearFromBuffer) {
-            int totalsize = START_DATA.length + 4 + size + END_DATA.length;
-            bufSize = bufSize - totalsize;
-            System.arraycopy(buf, totalsize, buf, 0, bufSize);
-        }
-        return xbuf;
-
-    }
-    
-    public ChannelData extractPackage(boolean clearFromBuffer) throws 
java.io.IOException {
-        XByteBuffer xbuf = extractDataPackage(clearFromBuffer);
-        ChannelData cdata = ChannelData.getDataFromPackage(xbuf);
-        return cdata;
-    }
-    
-    /**
-     * Creates a complete data package
-     * @param indata - the message data to be contained within the package
-     * @param compressed - compression flag for the indata buffer
-     * @return - 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(START_DATA, 0, data, offset, START_DATA.length);
-        offset += START_DATA.length;
-        toBytes(dlength,data, START_DATA.length);
-        offset += 4;
-        cdata.getDataPackage(data,offset);
-        offset += dlength;
-        System.arraycopy(END_DATA, 0, data, offset, END_DATA.length);
-        offset += END_DATA.length;
-        return data;
-    }
-    
-    public static byte[] createDataPackage(byte[] data, int doff, int dlength, 
byte[] buffer, int bufoff) {
-        if ( (buffer.length-bufoff) > getDataPackageLength(dlength) ) {
-            throw new ArrayIndexOutOfBoundsException("Unable to create data 
package, buffer is too small.");
-        }
-        System.arraycopy(START_DATA, 0, buffer, bufoff, START_DATA.length);
-        toBytes(data.length,buffer, bufoff+START_DATA.length);
-        System.arraycopy(data, doff, buffer, bufoff+START_DATA.length + 4, 
dlength);
-        System.arraycopy(END_DATA, 0, buffer, bufoff+START_DATA.length + 4 + 
data.length, END_DATA.length);
-        return buffer;
-    }
-
-    
-    public static int getDataPackageLength(int datalength) {
-        int length = 
-            START_DATA.length + //header length
-            4 + //data length indicator
-            datalength + //actual data length
-            END_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
-     * @param b - the byte array containing the four bytes
-     * @param off - the offset
-     * @return the integer value constructed from the four bytes
-     * @exception java.lang.ArrayIndexOutOfBoundsException
-     */
-    public static int toInt(byte[] b,int off){
-        return ( ( (int) b[off+3]) & 0xFF) +
-            ( ( ( (int) b[off+2]) & 0xFF) << 8) +
-            ( ( ( (int) b[off+1]) & 0xFF) << 16) +
-            ( ( ( (int) b[off+0]) & 0xFF) << 24);
-    }
-
-    /**
-     * Convert eight bytes to a long
-     * @param b - the byte array containing the four bytes
-     * @param off - the offset
-     * @return the long value constructed from the eight bytes
-     * @exception java.lang.ArrayIndexOutOfBoundsException
-     */
-    public static long toLong(byte[] b,int off){
-        return ( ( (long) b[off+7]) & 0xFF) +
-            ( ( ( (long) b[off+6]) & 0xFF) << 8) +
-            ( ( ( (long) b[off+5]) & 0xFF) << 16) +
-            ( ( ( (long) b[off+4]) & 0xFF) << 24) +
-            ( ( ( (long) b[off+3]) & 0xFF) << 32) +
-            ( ( ( (long) b[off+2]) & 0xFF) << 40) +
-            ( ( ( (long) b[off+1]) & 0xFF) << 48) +
-            ( ( ( (long) b[off+0]) & 0xFF) << 56);
-    }
-
-    
-    /**
-     * Converts an integer to four bytes
-     * @param n - the integer
-     * @return - four bytes in an array
-     * @deprecated use toBytes(boolean,byte[],int)
-     */
-    public static byte[] toBytes(boolean bool) {
-        byte[] b = new byte[1] ;
-        return toBytes(bool,b,0);
-
-    }
-    
-    public static byte[] toBytes(boolean bool, byte[] data, int offset) {
-        data[offset] = (byte)(bool?1:0);
-        return data;
-    }
-    
-    /**
-     * 
-     * @param <any> long
-     * @return use
-     */
-    public static boolean toBoolean(byte[] b, int offset) {
-        return b[offset] != 0;
-    }
-
-    
-    /**
-     * Converts an integer to four bytes
-     * @param n - the integer
-     * @return - four bytes in an array
-     * @deprecated use toBytes(int,byte[],int)
-     */
-    public static byte[] toBytes(int n) {
-        return toBytes(n,new byte[4],0);
-    }
-
-    public static byte[] toBytes(int n,byte[] b, int 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
-     * @param n - the long
-     * @return - eight bytes in an array
-     * @deprecated use toBytes(long,byte[],int)
-     */
-    public static byte[] toBytes(long n) {
-        return toBytes(n,new byte[8],0);
-    }
-    public static byte[] toBytes(long n, byte[] b, int 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
-     * @param src - the source bytes to be searched
-     * @param srcOff - offset on the source buffer
-     * @param find - the string to be found within src
-     * @return - the index of the first matching byte. -1 if the find array is 
not found
-     */
-    public static int firstIndexOf(byte[] src, int srcOff, byte[] find){
-        int result = -1;
-        if (find.length > src.length) return 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) 
-        throws IOException, ClassNotFoundException, ClassCastException {
-        return deserialize(data,0,data.length);
-    }
-    
-    public static Serializable deserialize(byte[] data, int offset, int 
length)  
-        throws IOException, ClassNotFoundException, ClassCastException {
-        return deserialize(data,offset,length,null);     
-    }
-    public static int invokecount = 0;
-    public static Serializable deserialize(byte[] data, int offset, int 
length, ClassLoader[] cls) 
-        throws IOException, ClassNotFoundException, ClassCastException {
-        synchronized (XByteBuffer.class) { invokecount++;}
-        Object message = null;
-        if ( cls == null ) cls = new ClassLoader[0];
-        if (data != null) {
-            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 (Serializable) message;
-        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
-     * @param msg ClusterMessage
-     * @param compress boolean
-     * @return 
-     * @throws IOException
-     */
-    public static byte[] serialize(Serializable msg) throws 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 = discard;
-    }
-
-    public boolean getDiscard() {
-        return discard;
-    }
-
-}
+/*
+ * 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;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+
+/**
+ * The XByteBuffer provides a dual functionality.
+ * One, it stores message bytes and automatically extends the byte buffer if 
needed.<BR>
+ * Two, it can encode and decode packages so that they can be defined and 
identified
+ * as they come in on a socket.
+ * <br>
+ * <b>THIS CLASS IS NOT THREAD SAFE</B><BR>
+ * <br/>
+ * Transfer package:
+ * <ul>
+ * <li><b>START_DATA/b> - 7 bytes - <i>FLT2002</i></li>
+ * <li><b>SIZE</b>      - 4 bytes - size of the data package</li>
+ * <li><b>DATA</b>      - should be as many bytes as the prev SIZE</li>
+ * <li><b>END_DATA</b>  - 7 bytes - <i>TLF2003</i></lI>
+ * </ul>
+ * @author Filip Hanik
+ * @version $Revision$, $Date$
+ */
+public class XByteBuffer
+{
+    
+    public static org.apache.juli.logging.Log log =
+        org.apache.juli.logging.LogFactory.getLog( XByteBuffer.class );
+    
+    /**
+     * This is a package header, 7 bytes (FLT2002)
+     */
+    public static final byte[] START_DATA = {70,76,84,50,48,48,50};
+    
+    /**
+     * This is the package footer, 7 bytes (TLF2003)
+     */
+    public static final byte[] END_DATA = {84,76,70,50,48,48,51};
+ 
+    /**
+     * Default size on the initial byte buffer
+     */
+    private static final int DEF_SIZE = 2048;
+ 
+    /**
+     * Default size to extend the buffer with
+     */
+    private static final int DEF_EXT  = 1024;
+    
+    /**
+     * 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 
+     * <code>START_DATA</code> it will be thrown away.
+     * 
+     */
+    protected boolean discard = true;
+    
+    /**
+     * Constructs a new XByteBuffer
+     * @param size - the initial size of the byte buffer
+     * @todo use a pool of byte[] for performance
+     */
+    public XByteBuffer(int size, boolean discard) {
+        buf = new byte[size];
+        this.discard = discard;
+    }
+    
+    public XByteBuffer(byte[] data,boolean discard) {
+        this(data,data.length+128,discard);
+    }
+    
+    public XByteBuffer(byte[] data, int size,boolean discard) {
+        int length = Math.max(data.length,size);
+        buf = new byte[length];
+        System.arraycopy(data,0,buf,0,data.length);
+        bufSize = data.length;
+        this.discard = discard;
+    }
+    
+    public int getLength() {
+        return bufSize;
+    }
+
+    public void setLength(int size) {
+        if ( size > buf.length ) throw new 
ArrayIndexOutOfBoundsException("Size is larger than existing buffer.");
+        bufSize = size;
+    }
+    
+    public void trim(int length) {
+        if ( (bufSize - length) < 0 ) 
+            throw new ArrayIndexOutOfBoundsException("Can't trim more bytes 
than are available. length:"+bufSize+" trim:"+length);
+        bufSize -= length;
+    }
+    
+    public void reset() {
+        bufSize = 0;
+    }
+            
+    public byte[] getBytesDirect() {
+        return this.buf;
+    }
+
+    /**
+     * Returns the bytes in the buffer, in its exact length
+     */
+    public byte[] getBytes() {
+        byte[] b = new byte[bufSize];
+        System.arraycopy(buf,0,b,0,bufSize);
+        return b;
+    }
+
+    /**
+     * Resets the buffer
+     */
+    public void clear() {
+        bufSize = 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.
+     * @param b - bytes to be appended
+     * @param off - the offset to extract data from
+     * @param len - the number of bytes to append.
+     * @return 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 b, int len) {
+        int newcount = bufSize + len;
+        if (newcount > buf.length) {
+            expand(newcount);
+        }
+        b.get(buf,bufSize,len);
+        
+        bufSize = newcount;
+        
+        if ( discard ) {
+            if (bufSize > START_DATA.length && (firstIndexOf(buf, 0, 
START_DATA) == -1)) {
+                bufSize = 0;
+                log.error("Discarded the package, invalid header");
+                return false;
+            }
+        }
+        return true;
+
+    }
+    
+    public boolean append(byte i) {
+        int newcount = bufSize + 1;
+        if (newcount > buf.length) {
+            expand(newcount);
+        }
+        buf[bufSize] = i;
+        bufSize = newcount;
+        return true;
+    }
+
+
+    public boolean append(boolean i) {
+        int newcount = bufSize + 1;
+        if (newcount > buf.length) {
+            expand(newcount);
+        }
+        XByteBuffer.toBytes(i,buf,bufSize);
+        bufSize = newcount;
+        return true;
+    }
+
+    public boolean append(long i) {
+        int newcount = bufSize + 8;
+        if (newcount > buf.length) {
+            expand(newcount);
+        }
+        XByteBuffer.toBytes(i,buf,bufSize);
+        bufSize = newcount;
+        return true;
+    }
+    
+    public boolean append(int i) {
+        int newcount = bufSize + 4;
+        if (newcount > buf.length) {
+            expand(newcount);
+        }
+        XByteBuffer.toBytes(i,buf,bufSize);
+        bufSize = newcount;
+        return true;
+    }
+
+    public boolean append(byte[] b, int off, int 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 = bufSize + len;
+        if (newcount > buf.length) {
+            expand(newcount);
+        }
+        System.arraycopy(b, off, buf, bufSize, len);
+        bufSize = newcount;
+
+        if ( discard ) {
+            if (bufSize > START_DATA.length && (firstIndexOf(buf, 0, 
START_DATA) == -1)) {
+                bufSize = 0;
+                log.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(buf.length << 1, newcount)];
+        System.arraycopy(buf, 0, newbuf, 0, bufSize);
+        buf = newbuf;
+    }
+    
+    public int getCapacity() {
+        return buf.length;
+    }
+
+
+    /**
+     * Internal mechanism to make a check if a complete package exists
+     * within the buffer
+     * @return - 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 = START_DATA.length;
+        int start = 0;
+
+        while ( start < bufSize ) {
+            //first check start header
+            int index = XByteBuffer.firstIndexOf(buf,start,START_DATA);
+            //if the header (START_DATA) isn't the first thing or
+            //the buffer isn't even 14 bytes
+            if ( index != start || ((bufSize-start)<14) ) break;
+            //next 4 bytes are compress flag not needed for count packages
+            //then get the size 4 bytes
+            int size = toInt(buf, pos);
+            //now the total buffer has to be long enough to hold
+            //START_DATA.length+4+size+END_DATA.length
+            pos = start + START_DATA.length + 4 + size;
+            if ( (pos + END_DATA.length) > bufSize) break;
+            //and finally check the footer of the package END_DATA
+            int newpos = firstIndexOf(buf, pos, END_DATA);
+            //mismatch, there is no package
+            if (newpos != pos) break;
+            //increase the packet count
+            cnt++;
+            //reset the values
+            start = pos + END_DATA.length;
+            pos = start + START_DATA.length;
+            //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.
+     * @return - 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.
+     * @param clearFromBuffer - if true, the package will be removed from the 
byte buffer
+     * @return - 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(buf, START_DATA.length);
+        XByteBuffer xbuf = BufferPool.getBufferPool().getBuffer(size,false);
+        xbuf.setLength(size);
+        System.arraycopy(buf, START_DATA.length + 4, xbuf.getBytesDirect(), 0, 
size);
+        if (clearFromBuffer) {
+            int totalsize = START_DATA.length + 4 + size + END_DATA.length;
+            bufSize = bufSize - totalsize;
+            System.arraycopy(buf, totalsize, buf, 0, bufSize);
+        }
+        return xbuf;
+
+    }
+    
+    public ChannelData extractPackage(boolean clearFromBuffer) throws 
java.io.IOException {
+        XByteBuffer xbuf = extractDataPackage(clearFromBuffer);
+        ChannelData cdata = ChannelData.getDataFromPackage(xbuf);
+        return cdata;
+    }
+    
+    /**
+     * Creates a complete data package
+     * @param indata - the message data to be contained within the package
+     * @param compressed - compression flag for the indata buffer
+     * @return - 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(START_DATA, 0, data, offset, START_DATA.length);
+        offset += START_DATA.length;
+        toBytes(dlength,data, START_DATA.length);
+        offset += 4;
+        cdata.getDataPackage(data,offset);
+        offset += dlength;
+        System.arraycopy(END_DATA, 0, data, offset, END_DATA.length);
+        offset += END_DATA.length;
+        return data;
+    }
+    
+    public static byte[] createDataPackage(byte[] data, int doff, int dlength, 
byte[] buffer, int bufoff) {
+        if ( (buffer.length-bufoff) > getDataPackageLength(dlength) ) {
+            throw new ArrayIndexOutOfBoundsException("Unable to create data 
package, buffer is too small.");
+        }
+        System.arraycopy(START_DATA, 0, buffer, bufoff, START_DATA.length);
+        toBytes(data.length,buffer, bufoff+START_DATA.length);
+        System.arraycopy(data, doff, buffer, bufoff+START_DATA.length + 4, 
dlength);
+        System.arraycopy(END_DATA, 0, buffer, bufoff+START_DATA.length + 4 + 
data.length, END_DATA.length);
+        return buffer;
+    }
+
+    
+    public static int getDataPackageLength(int datalength) {
+        int length = 
+            START_DATA.length + //header length
+            4 + //data length indicator
+            datalength + //actual data length
+            END_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
+     * @param b - the byte array containing the four bytes
+     * @param off - the offset
+     * @return the integer value constructed from the four bytes
+     * @exception java.lang.ArrayIndexOutOfBoundsException
+     */
+    public static int toInt(byte[] b,int off){
+        return ( ( (int) b[off+3]) & 0xFF) +
+            ( ( ( (int) b[off+2]) & 0xFF) << 8) +
+            ( ( ( (int) b[off+1]) & 0xFF) << 16) +
+            ( ( ( (int) b[off+0]) & 0xFF) << 24);
+    }
+
+    /**
+     * Convert eight bytes to a long
+     * @param b - the byte array containing the four bytes
+     * @param off - the offset
+     * @return the long value constructed from the eight bytes
+     * @exception java.lang.ArrayIndexOutOfBoundsException
+     */
+    public static long toLong(byte[] b,int off){
+        return ( ( (long) b[off+7]) & 0xFF) +
+            ( ( ( (long) b[off+6]) & 0xFF) << 8) +
+            ( ( ( (long) b[off+5]) & 0xFF) << 16) +
+            ( ( ( (long) b[off+4]) & 0xFF) << 24) +
+            ( ( ( (long) b[off+3]) & 0xFF) << 32) +
+            ( ( ( (long) b[off+2]) & 0xFF) << 40) +
+            ( ( ( (long) b[off+1]) & 0xFF) << 48) +
+            ( ( ( (long) b[off+0]) & 0xFF) << 56);
+    }
+
+    
+    /**
+     * Converts an integer to four bytes
+     * @param n - the integer
+     * @return - four bytes in an array
+     * @deprecated use toBytes(boolean,byte[],int)
+     */
+    public static byte[] toBytes(boolean bool) {
+        byte[] b = new byte[1] ;
+        return toBytes(bool,b,0);
+
+    }
+    
+    public static byte[] toBytes(boolean bool, byte[] data, int offset) {
+        data[offset] = (byte)(bool?1:0);
+        return data;
+    }
+    
+    /**
+     * 
+     * @param <any> long
+     * @return use
+     */
+    public static boolean toBoolean(byte[] b, int offset) {
+        return b[offset] != 0;
+    }
+
+    
+    /**
+     * Converts an integer to four bytes
+     * @param n - the integer
+     * @return - four bytes in an array
+     * @deprecated use toBytes(int,byte[],int)
+     */
+    public static byte[] toBytes(int n) {
+        return toBytes(n,new byte[4],0);
+    }
+
+    public static byte[] toBytes(int n,byte[] b, int 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
+     * @param n - the long
+     * @return - eight bytes in an array
+     * @deprecated use toBytes(long,byte[],int)
+     */
+    public static byte[] toBytes(long n) {
+        return toBytes(n,new byte[8],0);
+    }
+    public static byte[] toBytes(long n, byte[] b, int 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
+     * @param src - the source bytes to be searched
+     * @param srcOff - offset on the source buffer
+     * @param find - the string to be found within src
+     * @return - the index of the first matching byte. -1 if the find array is 
not found
+     */
+    public static int firstIndexOf(byte[] src, int srcOff, byte[] find){
+        int result = -1;
+        if (find.length > src.length) return 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) 
+        throws IOException, ClassNotFoundException, ClassCastException {
+        return deserialize(data,0,data.length);
+    }
+    
+    public static Serializable deserialize(byte[] data, int offset, int 
length)  
+        throws IOException, ClassNotFoundException, ClassCastException {
+        return deserialize(data,offset,length,null);     
+    }
+    public static int invokecount = 0;
+    public static Serializable deserialize(byte[] data, int offset, int 
length, ClassLoader[] cls) 
+        throws IOException, ClassNotFoundException, ClassCastException {
+        synchronized (XByteBuffer.class) { invokecount++;}
+        Object message = null;
+        if ( cls == null ) cls = new ClassLoader[0];
+        if (data != null) {
+            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 (Serializable) message;
+        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
+     * @param msg ClusterMessage
+     * @param compress boolean
+     * @return 
+     * @throws IOException
+     */
+    public static byte[] serialize(Serializable msg) throws 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 = discard;
+    }
+
+    public boolean getDiscard() {
+        return discard;
+    }
+
+}

Propchange: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/io/XByteBuffer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/tribes/io/XByteBuffer.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to