package com.mfq.business;
import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import com.mfq.utils.ArrayUtils;
import com.mfq.utils.CodeUtil;
public class BusinessDecode extends ProtocolDecoderAdapter{
private Logger log = Logger.getLogger(getClass());
private static final int HEAD_BODY_LENGTH = 6;
@Override
public void decode(IoSession session, IoBuffer buffer, ProtocolDecoderOutput out)
throws Exception {
try{
if(!buffer.hasRemaining()) return;
/** 报文体长度不足时用户回置 */
buffer.mark();
/** 获取缓存 */
MyByteBuffer myBuffer = (MyByteBuffer)session.getAttribute(CodeUtil.IOSESSION_BUFFER);
if(myBuffer!=null){
/** 首先尝试发送数据 */
myBuffer.sendPack(out);
/** 缓存包刚好发送完成则清除缓存包 */
if(myBuffer.getBufferLeng()==0){
session.removeAttribute(CodeUtil.IOSESSION_BUFFER);
myBuffer = null;
}
}
if(myBuffer!=null&&myBuffer.getBufferLeng()>0){//拥有缓存的情况下处理
/** 自定义缓存字节长度 */
int myLength = myBuffer.getBufferLeng();
/** 先获取缓冲字节 */
byte[] myByte = myBuffer.getBuffer();
int bodyLength = 0;
if(myLength >= HEAD_BODY_LENGTH){//缓存数据大于定义报文头长度下处理
int len = Integer.parseInt(new String(myByte, 0, HEAD_BODY_LENGTH), 10);
/** 获取剩余报文长度 */
bodyLength = len - myLength + HEAD_BODY_LENGTH;
}else{
byte[] headPart = new byte[HEAD_BODY_LENGTH - myLength];
if(buffer.remaining()<headPart.length){
setByteBuffer(buffer, session, myBuffer, out);
return;
}
buffer.get(headPart);
/** 合并头 */
byte[] head = ArrayUtils.concatByteArray(myByte, headPart);
bodyLength = Integer.parseInt(new String(head));
}
if(bodyLength>buffer.remaining()){//报文体长度不足时处理
buffer.reset();
setByteBuffer(buffer, session, myBuffer, out);
}else{//报文体长度合适处理
byte[] bodyPart = new byte[bodyLength];
buffer.get(bodyPart);
/** 合并两个包 */
out.write(new BusinessBean(ArrayUtils.concatByteArray(myByte, bodyPart)));
/** 刷新缓存 */
myBuffer.clearBuffer();
/** 判断是否还有字节,有则缓存。没有则移除session属性 */
if(buffer.hasRemaining()){
myBuffer.put(buffer);
}else{
session.removeAttribute(CodeUtil.IOSESSION_BUFFER);
}
}
}else{//无缓存情况下直接读取数据
byte[] length = new byte[HEAD_BODY_LENGTH];
/** 获取要读取的报文长度 */
buffer.get(length);
int len = Integer.parseInt(new String(length), 10);
buffer.reset();
/** 报文长度大于实际长度 */
if(len+HEAD_BODY_LENGTH > buffer.remaining()){
setByteBuffer(buffer, session, null, out);
}else{
byte[] body = new byte[len+HEAD_BODY_LENGTH];
buffer.get(body);
out.write(new BusinessBean(body));
if(buffer.hasRemaining()){
setByteBuffer(buffer, session, null, out);
}
}
}
}catch(Exception e){
out.write(new BusinessBean());
log.error("分析报文异常", e);
throw e;
}
}
/**
* 设置缓存
* @author littlehow
* @createtime 2015-7-3 下午5:00:41
*
* @param buffer
* @param session
* @param myBuffer
*/
private void setByteBuffer(IoBuffer buffer, IoSession session, MyByteBuffer myBuffer, ProtocolDecoderOutput out){
if(!buffer.hasRemaining()) return;
if(myBuffer==null){
myBuffer = new MyByteBuffer();
session.setAttribute(CodeUtil.IOSESSION_BUFFER, myBuffer);
}
myBuffer.put(buffer);
/** 尝试发送 */
myBuffer.sendPack(out);
}
/**
* 缓存管理类
* @author littlehow
* @createtime 2015-7-3 下午3:46:14
*
*/
static final class MyByteBuffer{
private Logger log = Logger.getLogger(getClass());
/** 缓存字节数的长度 */
private int bufferLeng = 0;
/** 缓存字节 */
private byte[] bts = null;
public MyByteBuffer(){
super();
}
public int getBufferLeng() {
return bufferLeng;
}
public byte[] getBuffer() {
return bts;
}
public void put(IoBuffer buffer){
try{
if(bufferLeng==0){
bufferLeng = buffer.remaining();
bts = new byte[bufferLeng];
buffer.get(bts);
}else{
bufferLeng += buffer.remaining();
byte[] tmp = new byte[buffer.remaining()];
buffer.get(tmp);
bts = ArrayUtils.concatByteArray(bts, tmp);
}
}catch(Exception e){
log.error("设置缓存数据异常", e);
}
buffer.clear();
buffer.flip();
}
public void clearBuffer(){
this.bts = null;
this.bufferLeng = 0;
}
/**
* 缓存数据大于一个包时发送
* @author littlehow
* @createtime 2015-7-3 下午5:09:13
*
* @param out
*/
public void sendPack(ProtocolDecoderOutput out){
if(this.bufferLeng==0) return;
while(send(out)){}
}
/**
* 真是发送信息
* @author littlehow
* @createtime 2015-7-3 下午5:13:21
*
* @param out
* @return
*/
private boolean send(ProtocolDecoderOutput out){
if(bufferLeng < HEAD_BODY_LENGTH) return false;
int bodyLength = Integer.parseInt(new String(bts, 0, HEAD_BODY_LENGTH), 10);
int allLeng = bodyLength+HEAD_BODY_LENGTH;
if(allLeng>bts.length) return false;
byte[] sendBys = new byte[allLeng];
System.arraycopy(bts, 0, sendBys, 0, allLeng);
out.write(new BusinessBean(sendBys));
bufferLeng = bts.length-allLeng;
if(bufferLeng==0){//缓存数据发送完毕
bts = null;
return false;
}
byte[] last = new byte[bufferLeng];
System.arraycopy(bts, allLeng, last, 0, bufferLeng);
this.bts = last;
return true;
}
}
}