All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.devsmart.miniweb.Server Maven / Gradle / Ivy

package com.devsmart.miniweb;

import org.apache.http.*;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.message.BasicStatusLine;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.*;
import java.util.concurrent.*;

public class Server {

    public final Logger logger = LoggerFactory.getLogger(Server.class);

    protected int port;
    protected HttpRequestHandlerResolver requestHandlerResolver;
    protected ConnectionPolicy connectionPolity;

    private final ExecutorService mWorkerThreads = Executors.newCachedThreadPool();

    private Thread mListenThread;
    private boolean mRunning = false;
    private BasicHttpContext mContext;

    public void start() throws IOException {

        if(mRunning){
            throw new IOException("server already running");
        }

        final ServerSocket mServerSocket = new ServerSocket(port);
        logger.info("Server started listening on {}", mServerSocket.getLocalSocketAddress());
        mServerSocket.setSoTimeout(1000);
        mRunning = true;

        mListenThread = new Thread(new Runnable() {
            @Override
            public void run() {
                // Set up the HTTP protocol processor

                mContext = new BasicHttpContext();
                BasicHttpProcessor httpproc = new BasicHttpProcessor();
                httpproc.addResponseInterceptor(new ResponseDate());
                httpproc.addResponseInterceptor(new ResponseServer());
                httpproc.addResponseInterceptor(new ResponseContent());
                httpproc.addResponseInterceptor(new ResponseConnControl());

                DefaultHttpResponseFactory responseFactory = new DefaultHttpResponseFactory();
                HttpParams params = new BasicHttpParams();
                HttpService httpService = new HttpService(httpproc, new DefaultConnectionReuseStrategy(), responseFactory);
                httpService.setHandlerResolver(requestHandlerResolver);
                httpService.setParams(params);

                while(mRunning){
                    try {
                        Socket socket = mServerSocket.accept();


                        if(connectionPolity.accept(socket)){
                            logger.debug("accepting connection from: {}", socket.getRemoteSocketAddress());

                            DefaultHttpServerConnection connection = new DefaultHttpServerConnection();
                            connection.bind(socket, new BasicHttpParams());
                            RemoteConnection remoteConnection = new RemoteConnection(socket.getInetAddress(), connection);
                            connectionPolity.connectionOpened(remoteConnection);
                            mWorkerThreads.execute(new WorkerTask(httpService, remoteConnection));
                        } else {
                            logger.debug("rejecting connection from: {}", socket);

                            try {
                                DefaultHttpServerConnection connection = new DefaultHttpServerConnection();
                                connection.bind(socket, new BasicHttpParams());
                                HttpResponse response = responseFactory.newHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_0, HttpStatus.SC_SERVICE_UNAVAILABLE, ""), mContext);
                                connection.sendResponseHeader(response);
                                connection.sendResponseEntity(response);
                                connection.flush();
                                connection.close();
                            } catch (Exception e) {}
                        }

                    } catch(SocketTimeoutException e) {
                    } catch (IOException e){
                        logger.error("", e);
                        mRunning = false;
                    }
                }

            }
        });
        mListenThread.setName("MiniWeb Listen " + mServerSocket.getLocalSocketAddress());
        mListenThread.start();

    }

    public void shutdown() {
        if(mRunning){
            mRunning = false;
            try {
                mListenThread.join();
                mListenThread = null;
            } catch (InterruptedException e) {
                logger.error("", e);
            }
            logger.info("Server shutdown");
        }
    }

    private class WorkerTask implements Runnable {

        private final HttpService httpservice;
        private final RemoteConnection remoteConnection;

        public WorkerTask(HttpService service, RemoteConnection connection){
            httpservice = service;
            remoteConnection = connection;
        }


        @Override
        public void run() {

            try {
                while(mRunning && remoteConnection.connection.isOpen()) {
                    httpservice.handleRequest(remoteConnection.connection, mContext);
                }
            } catch (ConnectionClosedException e) {
                logger.debug("client closed connection {}", remoteConnection.connection);

            } catch(SocketTimeoutException e){
                logger.debug("timing out connection {}", remoteConnection.connection);
                try {


                    DefaultHttpResponseFactory responseFactory = new DefaultHttpResponseFactory();
                    HttpResponse response = responseFactory.newHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_0, HttpStatus.SC_SERVICE_UNAVAILABLE, ""), mContext);


                    remoteConnection.connection.sendResponseHeader(response);
                    remoteConnection.connection.sendResponseEntity(response);
                    remoteConnection.connection.flush();
                } catch (Exception ex){
                    logger.error("", e);
                }

            } catch (IOException e) {
                logger.warn("IO error: " + e.getMessage());

            } catch (HttpException e) {
                logger.warn("Unrecoverable HTTP protocol violation: " + e.getMessage());

            } finally {
                shutdown();
            }


        }

        public void shutdown() {
            try {
                remoteConnection.connection.shutdown();
            } catch (IOException e){

            }
            finally {
                connectionPolity.connectionClosed(remoteConnection);
            }

        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy