com.github.mrstampy.gameboot.netty.AbstractNettyMessageHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.github.mrstampy.gameboot.netty.AbstractNettyMessageHandler.java

Source

/*
 *              ______                        ____              __ 
 *             / ____/___ _____ ___  ___     / __ )____  ____  / /_
 *            / / __/ __ `/ __ `__ \/ _ \   / __  / __ \/ __ \/ __/
 *           / /_/ / /_/ / / / / / /  __/  / /_/ / /_/ / /_/ / /_  
 *           \____/\__,_/_/ /_/ /_/\___/  /_____/\____/\____/\__/  
 *                                                 
 *                                 .-'\
 *                              .-'  `/\
 *                           .-'      `/\
 *                           \         `/\
 *                            \         `/\
 *                             \    _-   `/\       _.--.
 *                              \    _-   `/`-..--\     )
 *                               \    _-   `,','  /    ,')
 *                                `-_   -   ` -- ~   ,','
 *                                 `-              ,','
 *                                  \,--.    ____==-~
 *                                   \   \_-~\
 *                                    `_-~_.-'
 *                                     \-~
 * 
 *                       http://mrstampy.github.io/gameboot/
 *
 * Copyright (C) 2015, 2016 Burton Alexander
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * 
 */
package com.github.mrstampy.gameboot.netty;

import java.lang.invoke.MethodHandles;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.mrstampy.gameboot.controller.GameBootMessageController;
import com.github.mrstampy.gameboot.messages.AbstractGameBootMessage;
import com.github.mrstampy.gameboot.messaging.MessagingGroups;
import com.github.mrstampy.gameboot.processor.connection.ConnectionProcessor;
import com.github.mrstampy.gameboot.systemid.SystemId;
import com.github.mrstampy.gameboot.systemid.SystemIdKey;

import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;

/**
 * This class is the superclass for last-in-pipeline GameBoot Netty handlers.
 * Messages are presumed to have been converted to JSON strings representing an
 * {@link AbstractGameBootMessage} and are processed by the
 * {@link GameBootMessageController}. Channels are added to the
 * {@link MessagingGroups#ALL} group and registering the channel against the
 * {@link SystemId#next()} value obtained on connection. (The
 * {@link AbstractNettyMessageHandler#channelActive(ChannelHandlerContext)} and
 * {@link AbstractNettyMessageHandler#channelInactive(ChannelHandlerContext)}
 * must be called by subclasses overriding them.) <br>
 * <br>
 * 
 * Subclasses should have an annotated {@link PostConstruct} method which calls
 * the {@link AbstractNettyMessageHandler#postConstruct()}.<br>
 * <br>
 *
 * @param <C>
 *          the generic type
 * @param <CP>
 *          the generic type
 * @see GameBootMessageController
 */
public abstract class AbstractNettyMessageHandler<C, CP extends ConnectionProcessor<ChannelHandlerContext>>
        extends ChannelDuplexHandler {
    private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    private CP connectionProcessor;

    /**
     * Post construct created message counters if necessary. Subclasses will need
     * to invoke this in an annotated {@link PostConstruct} method.
     *
     * @throws Exception
     *           the exception
     */
    protected void postConstruct() throws Exception {
        if (connectionProcessor == null)
            throw new IllegalStateException("Netty Connection Processor not set");
    }

    /**
     * Subclasses overriding this method should remember to invoke it with a call
     * to 'super.'. Implementation generates a {@link SystemId} and puts the
     * channel in both the {@link MessagingGroups#ALL} group and against the
     * system id.
     *
     * @param ctx
     *          the ctx
     * @throws Exception
     *           the exception
     * 
     * @see #getSystemId()
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        connectionProcessor.onConnection(ctx);
    }

    /**
     * Subclasses overriding this method should remember to invoke it with a call
     * to 'super.'.
     *
     * @param ctx
     *          the ctx
     * @throws Exception
     *           the exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        connectionProcessor.onDisconnection(ctx);

        connectionProcessor = null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * io.netty.channel.ChannelInboundHandlerAdapter#exceptionCaught(io.netty.
     * channel.ChannelHandlerContext, java.lang.Throwable)
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("Unexpected error on {}, closing channel", ctx.channel(), cause);

        ctx.disconnect();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * io.netty.channel.ChannelInboundHandlerAdapter#channelRead(io.netty.channel.
     * ChannelHandlerContext, java.lang.Object)
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        connectionProcessor.onMessage(ctx, msg);
    }

    /**
     * Gets the key set in {@link #channelActive(ChannelHandlerContext)} from
     * {@link SystemId#next()}.
     *
     * @return the key
     */
    public SystemIdKey getSystemId() {
        return connectionProcessor.getSystemId(null);
    }

    /**
     * Gets the connection processor.
     *
     * @return the connection processor
     */
    public CP getConnectionProcessor() {
        return connectionProcessor;
    }

    /**
     * Sets the connection processor.
     *
     * @param connectionProcessor
     *          the new connection processor
     */
    public void setConnectionProcessor(CP connectionProcessor) {
        this.connectionProcessor = connectionProcessor;
    }

}