package com.pingan.emall.biz.communication.handler;
import com.pingan.emall.dto.MidResponseDTO;
import com.pingan.emall.util.StringUtil;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
/**
* 证券MID通讯返回解码器, 接收MID返回报文数据, 解析为基金频道对应的MIDResponseDTO对象
* 并写到FilterChain中交由下一个filter处理。
*
* doDecode方法复写了CumulativeProtocolDecoder中的abstract 方法, 用于处理网络断包,
* 当返回的IoBuffer中包含的bytes不足 , 将IoBuffer指针复位并返回通知父方法, 父方法会
* 根据返回结果决定是否将当前IoBuffer拼接到缓冲区中。
*
* @author LICHAO844
*
*/
public class FundTradeProtocolDecoder extends CumulativeProtocolDecoder {
private static Logger LOG = Logger.getLogger(FundTradeProtocolDecoder.class);
// length of response head length description string
private final static int RESPONSE_HEAD_LENGTH = 4;
private final static String SOH = "|";
private Charset charset;
public FundTradeProtocolDecoder(Charset charset) {
this.charset = charset == null ? Charset.defaultCharset() : charset;
}
@Override
protected boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception {
// Mark current position, if buffer is not enough, reset buffer.
in.mark();
// Get header length
if (in.remaining() < RESPONSE_HEAD_LENGTH) {
return false;
}
byte[] headLengthBytes = new byte[RESPONSE_HEAD_LENGTH];
in.get(headLengthBytes);
String headLengthStr = new String(headLengthBytes);
int headLength = Integer.parseInt(headLengthStr);
// Get the left data in header
if (in.remaining() < headLength - RESPONSE_HEAD_LENGTH) {
in.reset();
return false;
}
byte[] headBuffBytes = new byte[headLength - RESPONSE_HEAD_LENGTH];
in.get(headBuffBytes);
// Get header package
String headPackage = headLengthStr + new String(headBuffBytes, charset);
// Get body length
String[] headArray = StringUtil.split(headPackage, SOH);
int bodyLength = Integer.parseInt(headArray[1]);
// Get body package
if (in.remaining() < bodyLength) {
in.reset();
return false;
}
byte[] bodyBuffBytes = new byte[bodyLength];
in.get(bodyBuffBytes);
String bodyPackage = new String(bodyBuffBytes, charset);
out.write(parseResponsePackage(headPackage, bodyPackage));
if (LOG.isInfoEnabled()) {
String functionId = headArray[9];
String markedLog = FundTradeLogger.getMarkedInLog(functionId, headPackage + bodyPackage, session);
LOG.info(markedLog);
}
return true;
}
private MidResponseDTO parseResponsePackage(String headPackage, String bodyPackage) {
MidResponseDTO response = new MidResponseDTO();
// parse header package
String[] headArray = StringUtil.split(headPackage, SOH);
response.setResponseCode(Integer.parseInt(headArray[4]));
response.setResponseMessage(headArray[5]);
response.setHasNextPackage(Integer.parseInt(headArray[6]));
// parse body package
int fieldNum = Integer.parseInt(headArray[7]);
int rowNum = Integer.parseInt(headArray[8]);
if (rowNum > 0) {
List<Map<String, String>> resultList = new ArrayList<Map<String, String>>(rowNum);
String[] bodyArray = StringUtil.split(bodyPackage, SOH);
for (int k = 1; k <= rowNum; k++) {
Map<String, String> dataRow = new HashMap<String, String>(fieldNum);
int step = fieldNum * k;
for (int i = 0; i <= fieldNum - 1; i++) {
dataRow.put(bodyArray[i], bodyArray[i + step]);
}
resultList.add(dataRow);
}
response.setResultList(resultList);
}
return response;
}
}
import com.pingan.emall.dto.MidResponseDTO;
import com.pingan.emall.util.StringUtil;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
/**
* 证券MID通讯返回解码器, 接收MID返回报文数据, 解析为基金频道对应的MIDResponseDTO对象
* 并写到FilterChain中交由下一个filter处理。
*
* doDecode方法复写了CumulativeProtocolDecoder中的abstract 方法, 用于处理网络断包,
* 当返回的IoBuffer中包含的bytes不足 , 将IoBuffer指针复位并返回通知父方法, 父方法会
* 根据返回结果决定是否将当前IoBuffer拼接到缓冲区中。
*
* @author LICHAO844
*
*/
public class FundTradeProtocolDecoder extends CumulativeProtocolDecoder {
private static Logger LOG = Logger.getLogger(FundTradeProtocolDecoder.class);
// length of response head length description string
private final static int RESPONSE_HEAD_LENGTH = 4;
private final static String SOH = "|";
private Charset charset;
public FundTradeProtocolDecoder(Charset charset) {
this.charset = charset == null ? Charset.defaultCharset() : charset;
}
@Override
protected boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception {
// Mark current position, if buffer is not enough, reset buffer.
in.mark();
// Get header length
if (in.remaining() < RESPONSE_HEAD_LENGTH) {
return false;
}
byte[] headLengthBytes = new byte[RESPONSE_HEAD_LENGTH];
in.get(headLengthBytes);
String headLengthStr = new String(headLengthBytes);
int headLength = Integer.parseInt(headLengthStr);
// Get the left data in header
if (in.remaining() < headLength - RESPONSE_HEAD_LENGTH) {
in.reset();
return false;
}
byte[] headBuffBytes = new byte[headLength - RESPONSE_HEAD_LENGTH];
in.get(headBuffBytes);
// Get header package
String headPackage = headLengthStr + new String(headBuffBytes, charset);
// Get body length
String[] headArray = StringUtil.split(headPackage, SOH);
int bodyLength = Integer.parseInt(headArray[1]);
// Get body package
if (in.remaining() < bodyLength) {
in.reset();
return false;
}
byte[] bodyBuffBytes = new byte[bodyLength];
in.get(bodyBuffBytes);
String bodyPackage = new String(bodyBuffBytes, charset);
out.write(parseResponsePackage(headPackage, bodyPackage));
if (LOG.isInfoEnabled()) {
String functionId = headArray[9];
String markedLog = FundTradeLogger.getMarkedInLog(functionId, headPackage + bodyPackage, session);
LOG.info(markedLog);
}
return true;
}
private MidResponseDTO parseResponsePackage(String headPackage, String bodyPackage) {
MidResponseDTO response = new MidResponseDTO();
// parse header package
String[] headArray = StringUtil.split(headPackage, SOH);
response.setResponseCode(Integer.parseInt(headArray[4]));
response.setResponseMessage(headArray[5]);
response.setHasNextPackage(Integer.parseInt(headArray[6]));
// parse body package
int fieldNum = Integer.parseInt(headArray[7]);
int rowNum = Integer.parseInt(headArray[8]);
if (rowNum > 0) {
List<Map<String, String>> resultList = new ArrayList<Map<String, String>>(rowNum);
String[] bodyArray = StringUtil.split(bodyPackage, SOH);
for (int k = 1; k <= rowNum; k++) {
Map<String, String> dataRow = new HashMap<String, String>(fieldNum);
int step = fieldNum * k;
for (int i = 0; i <= fieldNum - 1; i++) {
dataRow.put(bodyArray[i], bodyArray[i + step]);
}
resultList.add(dataRow);
}
response.setResultList(resultList);
}
return response;
}
}