/*
* Copyright (C) 2012~2014 dinstone<dinstone@163.com>
*
* 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 com.dinstone.rpc.protocol;
import java.nio.ByteBuffer;
import java.util.Arrays;
import com.dinstone.rpc.serialize.SerializeType;
import com.dinstone.rpc.serialize.SerializerRegister;
/**
* RPC message codec.
*
* @author guojinfei
* @version 1.0.0.2014-6-23
*/
public class MessageCodec {
private static final SerializerRegister REGISTER = SerializerRegister.getInstance();
private MessageCodec() {
}
/**
* encode RPC Message.
*
* @param message
* RpcMessage
* @return
* @throws Exception
* serializable exception
*/
public static byte[] encodeMessage(Message<? extends IHeader, ? extends IContent> message) throws Exception {
IContent body = message.getContent();
byte[] bodyBytes = REGISTER.find(message.getSerializeType()).serialize(body);
ByteBuffer messageBuf = ByteBuffer.allocate(6 + bodyBytes.length);
messageBuf.putInt(message.getMessageId());
messageBuf.put(message.getMessageType().getValue());
messageBuf.put(message.getSerializeType().getValue());
messageBuf.put(bodyBytes);
messageBuf.flip();
return messageBuf.array();
}
/**
* decode RPC Message.
*
* @param rpcBytes
* RpcMessage bytes
* @return
* @throws Exception
* deserialize exception
*/
public static Message<? extends IHeader, ? extends IContent> decodeMessage(byte[] rpcBytes) throws Exception {
ByteBuffer messageBuf = ByteBuffer.wrap(rpcBytes);
// parse header
int messageId = messageBuf.getInt();
MessageType messageType = MessageType.valueOf(messageBuf.get());
SerializeType serializeType = SerializeType.valueOf(messageBuf.get());
byte[] bodyBytes = Arrays.copyOfRange(rpcBytes, 6, rpcBytes.length);
if (messageType == MessageType.RPC_REQUEST) {
Call call = REGISTER.find(serializeType).deserialize(bodyBytes, Call.class);
return new RpcRequest(messageId, serializeType, call);
} else if (messageType == MessageType.RPC_RESPONSE) {
Result result = REGISTER.find(serializeType).deserialize(bodyBytes, Result.class);
return new RpcResponse(messageId, serializeType, result);
} else if (messageType == MessageType.HEARTBEAT_PING) {
Ping ping = REGISTER.find(serializeType).deserialize(bodyBytes, Ping.class);
return new HeartbeatPing(messageId, ping);
} else if (messageType == MessageType.HEARTBEAT_PONG) {
Pong pong = REGISTER.find(serializeType).deserialize(bodyBytes, Pong.class);
return new HeartbeatPong(messageId, pong);
} else {
throw new IllegalStateException("unsupported content type [" + messageType + "]");
}
}
}