com.reversemind.hypergate.server.HyperGateServer.java Source code

Java tutorial

Introduction

Here is the source code for com.reversemind.hypergate.server.HyperGateServer.java

Source

/**
 * Copyright (c) 2013-2015 Eugene Kalinin
 * <p/>
 * 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
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * 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.reversemind.hypergate.server;

import com.reversemind.hypergate.Payload;
import org.apache.commons.lang3.StringUtils;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.serialization.ClassResolvers;
import org.jboss.netty.handler.codec.serialization.ObjectDecoder;
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.Serializable;
import java.net.*;
import java.util.Enumeration;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.Executors;

/**
 *
 * @author Eugene Kalinin
 */
public abstract class HyperGateServer implements IHyperGateServer, Serializable {

    private final static Logger LOG = LoggerFactory.getLogger(HyperGateServer.class);

    private String name;
    private String instanceName;
    private String host = "localhost";

    private boolean running = false;

    private ServerBootstrap serverBootstrap;
    private SimpleChannelUpstreamHandler handler;
    protected Metrics metrics;

    private int port;
    private boolean keepClientAlive = false;

    private Payload payload;
    private IPayloadProcessor payloadProcessor;

    /**
     * @param builder
     */
    public HyperGateServer(ServerFactory.Builder builder) {
        if (builder == null) {
            throw new RuntimeException("Builder is empty");
        }

        // parameter setAutoSelectPort has more priority than assigned setPort value
        if (builder.isAutoSelectPort()) {
            this.port = this.detectFreePort();
        } else if (builder.port() < 0) {
            this.port = this.detectFreePort();
        } else {
            this.port = builder.port();
        }

        if (builder.getPayloadWorker() == null) {
            throw new RuntimeException("Assign a setPayloadWorker to server!");
        }
        this.payloadProcessor = builder.getPayloadWorker();

        // drop connection from client or not
        LOG.warn(" =HyperGate= set value for KeepClientAlive from builder:" + builder.isKeepClientAlive());
        this.keepClientAlive = builder.isKeepClientAlive();

        this.name = StringUtils.isEmpty(builder.getName()) ? UUID.randomUUID().toString() : builder.getName();
        this.instanceName = StringUtils.isEmpty(builder.getInstanceName()) ? UUID.randomUUID().toString()
                : builder.getInstanceName();

        // TODO need to detect HOST NAME
        this.setHost(this.getIpAddress());

        this.metrics = new Metrics();
    }

    private String getIpAddress() {
        Set<String> ipSet = new TreeSet<String>();
        Enumeration<NetworkInterface> n = null;

        try {
            n = NetworkInterface.getNetworkInterfaces();

            for (; n.hasMoreElements();) {
                NetworkInterface e = n.nextElement();
                Enumeration<InetAddress> a = e.getInetAddresses();
                for (; a.hasMoreElements();) {
                    InetAddress inetAddress = a.nextElement();
                    if (inetAddress.getHostAddress() != null) {
                        ipSet.add(inetAddress.getHostAddress());
                    }
                }
            }

            if (ipSet != null && ipSet.size() > 0) {
                for (String ip : ipSet) {
                    if (!ip.equals("127.0.0.1") & !ip.equalsIgnoreCase("localhost")) {
                        return ip;
                    }
                }
            }

        } catch (SocketException se) {
            LOG.error("Socket exception", se);
        }

        return "localhost";
    }

    /**
     * Detect free setPort on System
     *
     * @return
     */
    private int detectFreePort() {
        try {
            ServerSocket serverSocket = new ServerSocket(0);
            if (serverSocket.getLocalPort() == -1) {
                System.exit(-100);
                throw new RuntimeException(
                        "\n\nCould not start HyperGateServer there are no any free port in the system available");
            }

            int detectedPortNumber = serverSocket.getLocalPort();

            serverSocket.close();
            int count = 0;
            while (!serverSocket.isClosed()) {
                if (count++ > 10) {
                    throw new RuntimeException("Could not start HyperGateServer");
                }
                try {
                    Thread.sleep(100);
                    LOG.info("Waiting for closing auto discovered socket try number#" + count);
                } catch (InterruptedException e) {
                    System.exit(-100);
                    throw new RuntimeException("Could not start HyperGateServer");
                }
            }
            serverSocket = null;

            return detectedPortNumber;
        } catch (IOException e) {
            e.printStackTrace();
        }
        throw new RuntimeException("Could not start HyperGateServer 'cause no any available free port in system");
    }

    /**
     * Get server setName
     *
     * @return
     */
    public String getName() {
        return name;
    }

    /**
     * Instance setName mostly prefer to use a UUID
     *
     * @return
     */
    public String getInstanceName() {
        return instanceName;
    }

    /**
     * Get setPort number of HyperGateServer
     *
     * @return
     */
    public int getPort() {
        return port;
    }

    /**
     * Get server metrics
     *
     * @return
     */
    public Metrics getMetrics() {
        return this.metrics;
    }

    /**
     *
     */
    public void start() {
        // Configure the server.
        this.serverBootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
                Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));

        this.handler = new ServerHandler(payloadProcessor, metrics, keepClientAlive);
        // TODO #6 KryoSerializer
        //        this.handler = new ServerHandler(payloadProcessor, metrics, keepClientAlive, this.kryoDeserializer);

        // Set up the pipeline factory
        // TODO add Kryo serializer
        this.serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                return Channels.pipeline(
                        //                        new KryoObjectEncoder(),
                        //                        new KryoObjectDecoder(ClassResolvers.cacheDisabled(getClass().getClassLoader())),
                        // TODO #6
                        new ObjectEncoder(),
                        new ObjectDecoder(ClassResolvers.cacheDisabled(getClass().getClassLoader())), handler);
            }
        });

        // Bind and start to accept incoming connections.
        this.serverBootstrap.bind(new InetSocketAddress(port));

        // TODO use CORRECT LOGGGING
        LOG.debug(this.toString());
        LOG.warn("\n\nServer started\n\n");

        // TODO need to detect HOST NAME
        this.setHost(this.getIpAddress());
        this.running = true;
    }

    public boolean isRunning() {
        return this.running;
    }

    /**
     * Shutdown server
     */
    public void shutdown() {
        if (this.serverBootstrap != null) {
            this.serverBootstrap.releaseExternalResources();
            this.serverBootstrap.shutdown();

            this.port = -1;
            this.running = false;

            this.name = null;
            this.instanceName = null;
            this.host = null;
        }
    }

    private void setHost(String hostName) {
        // TODO remove from test implementation code
        this.host = hostName;
    }

    public String getHost() {
        // TODO remove from test implementation code
        return this.host;
    }

    @Override
    public String toString() {
        return "\n\n\n" + " HyperGateServer " + "\n-------------------" + "\n setName:" + this.name + "\n instance:"
                + this.instanceName + "\n port:" + this.port + "\n host:" + this.host + "\n metrics:" + this.metrics
                + "  \n\n\n";
    }

}