📄 xbytebuffer.java
字号:
/* * Copyright 1999,2004-2005 The Apache Software Foundation. * * Licensed 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.ObjectOutputStream;import java.io.Serializable;import java.nio.ByteBuffer;import java.io.ObjectInputStream;/** * 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>OPTIONS</b> - 4 bytes - message options, implementation specific</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.commons.logging.Log log = org.apache.commons.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; /** * * */ protected boolean discard = true; /** * Constructs a new XByteBuffer * @param size - the initial size of the byte buffer */ 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 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 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() { 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; } return cnt; } /** * Method to check if a package exists in this byte buffer.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -