org.asciidoctor.maven.http.AsciidoctorHttpServer.java Source code

Java tutorial

Introduction

Here is the source code for org.asciidoctor.maven.http.AsciidoctorHttpServer.java

Source

/*
 * 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 org.asciidoctor.maven.http;

import java.io.File;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.concurrent.Future;

import org.apache.maven.plugin.logging.Log;

public class AsciidoctorHttpServer {
    private static final String HOST = "localhost";
    private static final int THREAD_NUMBER = 3;
    private static final String THREAD_PREFIX = "asciidoctor-thread-";

    private final Log logger;
    private final int port;
    private final File workDir;
    private final String defaultPage;

    private ServerBootstrap bootstrap;
    private NioEventLoopGroup workerGroup;

    public AsciidoctorHttpServer(final Log logger, final int port, final File outputDirectory,
            final String defaultPage) {
        this.logger = logger;
        this.port = port;
        this.workDir = outputDirectory;
        this.defaultPage = defaultPage;
    }

    public void start() {
        final AtomicInteger threadId = new AtomicInteger(1);
        workerGroup = new NioEventLoopGroup(THREAD_NUMBER, new ThreadFactory() {
            @Override
            public Thread newThread(final Runnable r) {
                final Thread t = new Thread(r, THREAD_PREFIX + threadId.getAndIncrement());
                if (t.getPriority() != Thread.NORM_PRIORITY) {
                    t.setPriority(Thread.NORM_PRIORITY);
                }
                if (t.isDaemon()) {
                    t.setDaemon(false);
                }
                return t;
            }
        });

        try {
            bootstrap = new ServerBootstrap();
            bootstrap.option(ChannelOption.SO_REUSEADDR, true).option(ChannelOption.SO_SNDBUF, 1024)
                    .option(ChannelOption.TCP_NODELAY, true).group(workerGroup)
                    .channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(final SocketChannel ch) throws Exception {
                            ch.pipeline().addLast("decoder", new HttpRequestDecoder())
                                    .addLast("aggregator", new HttpObjectAggregator(Integer.MAX_VALUE))
                                    .addLast("encoder", new HttpResponseEncoder())
                                    .addLast("chunked-writer", new ChunkedWriteHandler())
                                    .addLast("asciidoctor", new AsciidoctorHandler(workDir, defaultPage));
                        }
                    }).bind(port).addListener(new ChannelFutureListener() {
                        @Override
                        public void operationComplete(final ChannelFuture future) throws Exception {
                            if (!future.isSuccess()) {
                                logger.error("Can't start HTTP server");
                            } else {
                                logger.info(String.format("Server started on http://%s:%s", HOST, port));
                            }
                        }
                    }).sync();
        } catch (final InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
    }

    public void stop() {
        Future<?> shutdownGracefully = workerGroup.shutdownGracefully();
        logger.info("Server stopping...");
        try {
            shutdownGracefully.get();
            logger.info("Server stopped");
        } catch (InterruptedException e) {
            logger.error(e);
        } catch (ExecutionException e) {
            logger.error(e);
        }
    }

}