com.yea.remote.netty.codec.NettyMessageEncoder.java Source code

Java tutorial

Introduction

Here is the source code for com.yea.remote.netty.codec.NettyMessageEncoder.java

Source

/**
 * Copyright 2017 
 *
 * 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.yea.remote.netty.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;

import com.yea.core.compress.Compress;
import com.yea.core.remote.constants.RemoteConstants;
import com.yea.core.remote.struct.Message;
import com.yea.core.serializer.ISerializer;
import com.yea.core.serializer.pool.SerializePool;
import com.yea.remote.netty.handle.NettyChannelHandler;

/**
 * ???FST
 * @author yiyongfei
 * 
 */
public final class NettyMessageEncoder extends MessageToByteEncoder<Message> implements NettyChannelHandler {
    private static final byte[] LENGTH_PLACEHOLDER = new byte[4];
    private SerializePool serializePool;
    private RemoteConstants.CompressionAlgorithm compressionAlgorithm;

    public NettyMessageEncoder() {
        this(null);
    }

    public NettyMessageEncoder(RemoteConstants.CompressionAlgorithm compressionAlgorithm) {
        this.serializePool = new SerializePool();
        this.compressionAlgorithm = compressionAlgorithm;
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf sendBuf) throws Exception {
        if (msg == null || msg.getHeader() == null) {
            throw new Exception("The encode message is null");
        }
        ISerializer serializer = serializePool.borrow();
        try {
            long basedate = new Date().getTime();
            sendBuf.writeInt((msg.getHeader().getCrcCode()));// 4
            sendBuf.writeInt((msg.getHeader().getLength()));// 4Header+BodyHeader18
            sendBuf.writeBytes((msg.getHeader().getSessionID()));// 16
            sendBuf.writeByte((msg.getHeader().getType()));// 1
            sendBuf.writeByte((msg.getHeader().getPriority()));// 1
            sendBuf.writeByte((msg.getHeader().getResult()));// 1
            if (compressionAlgorithm != null && compressionAlgorithm.code() > 0) {
                // 
                serializer.setCompress(new Compress().setCompressionAlgorithm(compressionAlgorithm.algorithm()));
                sendBuf.writeByte(compressionAlgorithm.ordinal());
            } else {
                sendBuf.writeByte(RemoteConstants.CompressionAlgorithm.NONE.ordinal());
            }
            sendBuf.writeLong(basedate);// 8??
            if (msg.getHeader().getAttachment() != null && !msg.getHeader().getAttachment().isEmpty()) {
                sendBuf.writeByte(msg.getHeader().getAttachment().size());
                Map<String, Number> mapDateType = new HashMap<String, Number>();// Date
                Map<String, String> mapStringType = new HashMap<String, String>();// String

                int lengthPos = sendBuf.writerIndex();
                sendBuf.writeBytes(new byte[1]);// 1?Date?
                byte[] keyArray = null;
                byte[] valueArray = null;
                for (Map.Entry<String, Object> param : msg.getHeader().getAttachment().entrySet()) {
                    if (param.getValue() instanceof Date) {
                        //Date???byte
                        long time = basedate - ((Date) param.getValue()).getTime();
                        if (time > Integer.MAX_VALUE) {
                            mapDateType.put(param.getKey(), new Long(time));
                        } else if (time > Short.MAX_VALUE) {
                            mapDateType.put(param.getKey(), new Integer((int) time));
                        } else if (time > Byte.MAX_VALUE) {
                            mapDateType.put(param.getKey(), new Short((short) time));
                        } else {
                            mapDateType.put(param.getKey(), new Byte((byte) time));
                        }
                    } else if (param.getValue() instanceof String) {
                        //??getBytes()?
                        mapStringType.put(param.getKey(), (String) param.getValue());
                    } else {
                        keyArray = param.getKey().getBytes("ISO-8859-1");
                        sendBuf.writeShort(keyArray.length);
                        sendBuf.writeBytes(keyArray);

                        valueArray = serializer.serialize(param.getValue());
                        sendBuf.writeShort(valueArray.length);
                        sendBuf.writeBytes(valueArray);
                    }
                }
                sendBuf.setByte(lengthPos,
                        msg.getHeader().getAttachment().size() - mapDateType.size() - mapStringType.size());

                if (mapDateType.isEmpty()) {
                    sendBuf.writeByte(0);// 1Date?0
                } else {
                    sendBuf.writeByte(mapDateType.size());// 1Date?
                    for (Map.Entry<String, Number> param : mapDateType.entrySet()) {
                        keyArray = param.getKey().getBytes("ISO-8859-1");
                        sendBuf.writeShort(keyArray.length);
                        sendBuf.writeBytes(keyArray);

                        if (param.getValue() instanceof Long) {
                            sendBuf.writeByte(8);
                            sendBuf.writeLong((Long) param.getValue());
                        } else if (param.getValue() instanceof Integer) {
                            sendBuf.writeByte(4);
                            sendBuf.writeInt((Integer) param.getValue());
                        } else if (param.getValue() instanceof Short) {
                            sendBuf.writeByte(2);
                            sendBuf.writeShort((Short) param.getValue());
                        } else {
                            sendBuf.writeByte(1);
                            sendBuf.writeByte((Byte) param.getValue());
                        }
                    }
                }

                if (mapStringType.isEmpty()) {
                    sendBuf.writeByte(0);// 1String?0
                } else {
                    sendBuf.writeByte(mapStringType.size());// 1String?
                    for (Map.Entry<String, String> param : mapStringType.entrySet()) {
                        keyArray = param.getKey().getBytes("ISO-8859-1");
                        sendBuf.writeShort(keyArray.length);
                        sendBuf.writeBytes(keyArray);

                        valueArray = param.getValue().getBytes("ISO-8859-1");
                        sendBuf.writeShort(valueArray.length);
                        sendBuf.writeBytes(valueArray);
                    }
                }
            } else {
                sendBuf.writeByte(0);// 20
            }

            if (msg.getBody() != null) {
                byte[] objArray = serializer.serialize(msg.getBody());
                int lengthPos = sendBuf.writerIndex();
                sendBuf.writeBytes(LENGTH_PLACEHOLDER);// 4Body
                sendBuf.writeBytes(objArray);
                sendBuf.setInt(lengthPos, sendBuf.writerIndex() - lengthPos - 4);// Body
            } else {
                sendBuf.writeInt(0);
            }
            sendBuf.setInt(4, sendBuf.readableBytes() - 8);// Header+Body
        } finally {
            serializePool.restore(serializer);
        }
    }

    public ChannelHandler clone() throws CloneNotSupportedException {
        NettyMessageEncoder obj = null;
        obj = (NettyMessageEncoder) super.clone();
        return obj;
    }

    @SuppressWarnings("unused")
    private ApplicationContext context;

    /** 
     * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
     */
    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
        context = arg0;
    }

}