package com.cwa.protobuf; import com.cwa.gamecore.io.GameInput; import com.cwa.gamecore.io.GameOutput; import com.cwa.gamecore.message.GameMessage; import com.cwa.gamecore.util.StringUtil; import com.google.protobuf.CodedInputStream; import com.google.protobuf.MessageLite; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.apache.log4j.Logger; /** * GameMessage实现。内部封装了MessageLite。 */ public class ProtobufGameMessage implements GameMessage { private static final Logger logger = Logger.getLogger(ProtobufGameMessage.class); private static final int PROTOBUF_MSG_ID = 100; int msgId; private MessageLite message; @Override public int getCommandId() { return PROTOBUF_MSG_ID; } public MessageLite getMessage() { return message; } public void setMessage(MessageLite message) { this.message = message; } @Override public void decodeBody(GameInput in) { byte[] data = in.getBytes(); if (logger.isDebugEnabled()) { logger.debug("Decode protobuf request:"); logger.debug(StringUtil.toDebugString(data)); } try { // get msg id msgId = readMsgId(data); // parse msg message = ProtobufSupport.parseRequest(msgId, data); } catch (IOException e) { throw new ProtobufException("Failed to decode request!", e); } } private int readMsgId(byte[] msgData) throws IOException { CodedInputStream tmp = CodedInputStream.newInstance(msgData); tmp.readTag(); return tmp.readInt32(); } @Override public void encodeBody(GameOutput out) { try { ByteArrayOutputStream os = new ByteArrayOutputStream(); message.writeTo(os); byte[] data = os.toByteArray(); out.putBytes(data); if (logger.isDebugEnabled()) { logger.debug("Encode protobuf response:"); logger.debug(StringUtil.toDebugString(data)); } } catch (IOException e) { throw new ProtobufException("Failed to encode response!", e); } } @Override public String toString() { return "{ProtobufGameMessage" + " msgId=" + msgId + " proto=" + (message == null ? null : message.getClass().getSimpleName()) + "}"; } // 工厂方法 public static ProtobufGameMessage wrap(MessageLite msg) { ProtobufGameMessage wrapper = new ProtobufGameMessage(); wrapper.setMessage(msg); return wrapper; } }