de.saxsys.synchronizefx.netty.base.server.NettyBasicServer.java Source code

Java tutorial

Introduction

Here is the source code for de.saxsys.synchronizefx.netty.base.server.NettyBasicServer.java

Source

/**
 * This file is part of SynchronizeFX.
 * 
 * Copyright (C) 2013-2014 Saxonia Systems AG
 *
 * SynchronizeFX is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SynchronizeFX 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with SynchronizeFX. If not, see <http://www.gnu.org/licenses/>.
 */

package de.saxsys.synchronizefx.netty.base.server;

import java.util.List;

import de.saxsys.synchronizefx.core.clientserver.CommandTransferServer;
import de.saxsys.synchronizefx.core.clientserver.NetworkToTopologyCallbackServer;
import de.saxsys.synchronizefx.core.exceptions.SynchronizeFXException;
import de.saxsys.synchronizefx.core.metamodel.commands.Command;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.ChannelMatcher;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.GlobalEventExecutor;

/**
 * Contains the base server implementation for all Netty based {@link CommandTransferServer}s.
 */
public abstract class NettyBasicServer implements CommandTransferServer {

    private NioEventLoopGroup connectionAccptorGroup;
    private NioEventLoopGroup clientConnectionGroup;

    private ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    private final int port;
    private NetworkToTopologyCallbackServer callback;

    /**
     * Initializes an instance.
     * 
     * @param port The port to listen on when the server is {@link #start()}ed.
     */
    public NettyBasicServer(final int port) {
        this.port = port;
    }

    /**
     * Creates an channel pipeline implementation with data codecs specific to the concrete implementation of this
     * base server.
     * 
     * @return The created initializer
     */
    protected abstract BasicChannelInitializerServer createChannelInitializer();

    @Override
    public void start() throws SynchronizeFXException {
        this.connectionAccptorGroup = new NioEventLoopGroup();
        this.clientConnectionGroup = new NioEventLoopGroup();

        BasicChannelInitializerServer channelInitializer = createChannelInitializer();
        channelInitializer.setTopologyCallback(callback);

        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(connectionAccptorGroup, clientConnectionGroup).channel(NioServerSocketChannel.class)
                .childHandler(channelInitializer).childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.SO_KEEPALIVE, true);

        bootstrap.bind(port).syncUninterruptibly();
    }

    @Override
    public void setTopologyLayerCallback(final NetworkToTopologyCallbackServer callback) {
        this.callback = callback;
    }

    @Override
    public void onConnectFinished(final Object client) {
        clients.add((Channel) client);
    }

    @Override
    public void sendToAll(final List<Command> commands) {
        clients.writeAndFlush(commands);
    }

    @Override
    public void send(final List<Command> commands, final Object client) {
        ((Channel) client).writeAndFlush(commands);
    }

    @Override
    public void sendToAllExcept(final List<Command> commands, final Object nonReciver) {
        clients.writeAndFlush(commands, new ChannelMatcher() {
            @Override
            public boolean matches(final Channel candidate) {
                return candidate != nonReciver;
            }
        });
    }

    @Override
    public void shutdown() {
        connectionAccptorGroup.shutdownGracefully().addListener(new GenericFutureListener<Future<Object>>() {
            @Override
            public void operationComplete(final Future<Object> future) throws Exception {
                clientConnectionGroup.shutdownGracefully();
            }
        });
    };
}