Package de.uniluebeck.itm.ncoap.application.server

Source Code of de.uniluebeck.itm.ncoap.application.server.CoapServerApplication

/**
* Copyright (c) 2012, Oliver Kleine, Institute of Telematics, University of Luebeck
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
*  - Redistributions of source messageCode must retain the above copyright notice, this list of conditions and the following
*    disclaimer.
*
*  - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
*    following disclaimer in the documentation and/or other materials provided with the distribution.
*
*  - Neither the name of the University of Luebeck nor the names of its contributors may be used to endorse or promote
*    products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package de.uniluebeck.itm.ncoap.application.server;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import de.uniluebeck.itm.ncoap.application.server.webservice.Webservice;
import de.uniluebeck.itm.ncoap.communication.dispatching.server.NotFoundHandler;
import de.uniluebeck.itm.ncoap.communication.dispatching.server.WebserviceManager;
import de.uniluebeck.itm.ncoap.communication.reliability.InboundReliabilityHandler;
import de.uniluebeck.itm.ncoap.communication.reliability.OutboundReliabilityHandler;
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.DatagramChannel;
import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
import org.jboss.netty.util.ThreadNameDeterminer;
import org.jboss.netty.util.ThreadRenamingRunnable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;


/**
* An instance of {@link CoapServerApplication} is the component to enable instances of {@link de.uniluebeck.itm.ncoap.application.server.webservice.Webservice} to
* communicate with the outside world, i.e. the Internet. Once a {@link CoapServerApplication} was instanciated
* one can register {@link de.uniluebeck.itm.ncoap.application.server.webservice.Webservice} instances and by this means make them available at their specified path.
*
* Each instance of {@link CoapServerApplication} is automatically bound to a local port to listen at for
* inbound requests.
*
* @author Oliver Kleine
*/
public class CoapServerApplication{

    public static final int DEFAULT_COAP_SERVER_PORT = 5683;

    private Logger log = LoggerFactory.getLogger(this.getClass().getName());

    private WebserviceManager webserviceManager;
    private DatagramChannel channel;
    private ScheduledExecutorService executor;

    /**
     * Creates a new instance of {@link de.uniluebeck.itm.ncoap.application.server.CoapServerApplication}
     *
     * @param webServiceNotFoundHandler to handle inbound {@link de.uniluebeck.itm.ncoap.message.CoapRequest}s
     *                                  targeting unknown services
     * @param localSocket the IP address and port number for the server to listen at
     */
    public CoapServerApplication(NotFoundHandler webServiceNotFoundHandler, InetSocketAddress localSocket){

        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("CoAP Server I/O Thread#%d").build();

        ThreadRenamingRunnable.setThreadNameDeterminer(new ThreadNameDeterminer() {
            @Override
            public String determineThreadName(String currentThreadName, String proposedThreadName) throws Exception {
                return null;
            }
        });

        int numberOfThreads = Math.max(Runtime.getRuntime().availableProcessors() * 2, 4);
        log.info("No. of I/O Threads: {}", numberOfThreads);

        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(numberOfThreads, threadFactory);
        executor.setRemoveOnCancelPolicy(true);
        this.executor = executor;

        //Create bootstrap
        ChannelFactory channelFactory = new NioDatagramChannelFactory(this.executor, numberOfThreads/2);
        ConnectionlessBootstrap bootstrap = new ConnectionlessBootstrap(channelFactory);

        ServerChannelPipelineFactory pipelineFactory =
                new ServerChannelPipelineFactory(this.executor, webServiceNotFoundHandler);


        bootstrap.setPipelineFactory(pipelineFactory);

        this.channel = (DatagramChannel) bootstrap.bind(localSocket);
        log.debug("Bound to local address: {}", this.channel.getLocalAddress());

        this.webserviceManager =
                (WebserviceManager) pipelineFactory.getChannelHandler(ServerChannelPipelineFactory.WEBSERVICE_MANAGER);

        this.webserviceManager.setChannel(channel);

        webServiceNotFoundHandler.setWebserviceManager(webserviceManager);

        //Set the ChannelHandlerContext for the outbound reliability handler
        OutboundReliabilityHandler outboundReliabilityHandler =
                (OutboundReliabilityHandler) this.channel.getPipeline()
                                 .get(ServerChannelPipelineFactory.OUTBOUND_RELIABILITY_HANDLER);

        outboundReliabilityHandler.setChannelHandlerContext(
                this.channel.getPipeline()
                        .getContext(ServerChannelPipelineFactory.OUTBOUND_RELIABILITY_HANDLER)
        );

        //Set the ChannelHandlerContext for the inbound reliability handler
        InboundReliabilityHandler inboundReliabilityHandler =
                         (InboundReliabilityHandler) this.channel.getPipeline()
                                 .get(ServerChannelPipelineFactory.INBOUND_RELIABILITY_HANDLER);

        inboundReliabilityHandler.setChannelHandlerContext(
                this.channel.getPipeline()
                        .getContext(ServerChannelPipelineFactory.INBOUND_RELIABILITY_HANDLER)
        );
    }

    public CoapServerApplication(InetSocketAddress localSocketAddress){
        this(NotFoundHandler.getDefault(), localSocketAddress);
    }


    /**
     * <p>Creates a new instance of {@link de.uniluebeck.itm.ncoap.application.server.CoapServerApplication}</p>
     *
     * <p><b>Note:</b> An instance created with this constructor uses
     * {@link de.uniluebeck.itm.ncoap.communication.dispatching.server.NotFoundHandler#getDefault()} to handle
     * {@link de.uniluebeck.itm.ncoap.message.CoapRequest}s targeting unknown services.
     *
     * @param serverPort the port number for the server to listen at (holds for all IP addresses of the server)
     */
    public CoapServerApplication(int serverPort){
        this(NotFoundHandler.getDefault(), new InetSocketAddress(serverPort));
    }

    /**
     * Creates a new instance of {@link de.uniluebeck.itm.ncoap.application.server.CoapServerApplication}
     *
     * @param webServiceNotFoundHandler to handle inbound {@link de.uniluebeck.itm.ncoap.message.CoapRequest}s
     *                                  targeting unknown services
     * @param serverPort the port number for the server to listen at (holds for all IP addresses of the server)
     */
    public CoapServerApplication(NotFoundHandler webServiceNotFoundHandler, int serverPort){
        this(webServiceNotFoundHandler, new InetSocketAddress(serverPort));
    }

    /**
     * <p>Creates a new instance of {@link de.uniluebeck.itm.ncoap.application.server.CoapServerApplication}</p>
     *
     * <p><b>Note:</b> An instance created with this constructor uses
     * {@link de.uniluebeck.itm.ncoap.communication.dispatching.server.NotFoundHandler#getDefault()} to handle
     * {@link de.uniluebeck.itm.ncoap.message.CoapRequest}s targeting unknown services and listens on port
     * {@link #DEFAULT_COAP_SERVER_PORT} (all IP addresses)
     */
    public CoapServerApplication(){
        this(DEFAULT_COAP_SERVER_PORT);
    }

    /**
     * <p>Creates a new instance of {@link de.uniluebeck.itm.ncoap.application.server.CoapServerApplication}</p>
     *
     * <p><b>Note:</b> An instance created with this constructor listens on port
     * {@link #DEFAULT_COAP_SERVER_PORT} (all IP addresses)
     */
    public CoapServerApplication(NotFoundHandler webServiceNotFoundHandler){
        this(webServiceNotFoundHandler, DEFAULT_COAP_SERVER_PORT);
    }


    /**
     * Registeres a new {@link de.uniluebeck.itm.ncoap.application.server.webservice.Webservice} at this
     * {@link de.uniluebeck.itm.ncoap.application.server.CoapServerApplication}.
     *
     * @param webservice the {@link de.uniluebeck.itm.ncoap.application.server.webservice.Webservice} instance to
     *                   be registered
     */
    public void registerService(Webservice webservice){
        WebserviceManager manager =
                (WebserviceManager)this.channel.getPipeline().get(ServerChannelPipelineFactory.WEBSERVICE_MANAGER);

        manager.registerService(webservice);
    }


    /**
     * Returns the port number this {@link de.uniluebeck.itm.ncoap.application.server.CoapServerApplication} listens at
     * @return the port number this {@link de.uniluebeck.itm.ncoap.application.server.CoapServerApplication} listens at
     */
    public int getPort(){
        return this.channel.getLocalAddress().getPort();
    }


    /**
     * Returns the {@link java.util.concurrent.ScheduledExecutorService} which is used by this
     * {@link de.uniluebeck.itm.ncoap.application.server.CoapServerApplication} to handle tasks, e.g. write and
     * receive messages. The returned {@link java.util.concurrent.ScheduledExecutorService} may also be used by
     * {@link de.uniluebeck.itm.ncoap.application.server.webservice.Webservice}s to handle inbound
     * {@link de.uniluebeck.itm.ncoap.message.CoapRequest}s
     *
     * @return the {@link java.util.concurrent.ScheduledExecutorService} which is used by this
     * {@link de.uniluebeck.itm.ncoap.application.server.CoapServerApplication} to handle tasks, e.g. write and
     * receive messages.
     */
    public ScheduledExecutorService getExecutor(){
        return this.executor;
    }


    /**
     * Gracefully shuts down the server by sequentially shutting down all its components, i.e. the registered
     * {@link de.uniluebeck.itm.ncoap.application.server.webservice.Webservice}s and the
     * {@link org.jboss.netty.channel.socket.DatagramChannel} to write and receive messages.
     */
    public void shutdown(){
        log.warn("Shutdown server...");

        this.webserviceManager.shutdownAllServices();

        ChannelFuture channelClosedFuture = this.channel.close();

        //Await the closure and let the factory release its external resource to finalize the shutdown
        channelClosedFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                log.warn("Server channel closed. Release external resources...");

                channel.getFactory().releaseExternalResources();
            }
        });

        channelClosedFuture.awaitUninterruptibly().addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                log.warn("Server shutdown completed!");
            }
        });
    }
}
TOP

Related Classes of de.uniluebeck.itm.ncoap.application.server.CoapServerApplication

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.