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

service.AbstractService Maven / Gradle / Ivy

package service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import socket.Code;
import socket.Server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicReference;

public abstract class AbstractService implements Service, AutoCloseable {
    public static class InvalidCommandException extends Exception{
        public InvalidCommandException(String message) {
            super(message);
        }
    }

    public static class InvalidFormatException extends Exception{
        public InvalidFormatException(String message) {
            super(message);
        }
    }

    private class ClientHandler implements Code {
        private final Logger LOGGER = LoggerFactory.getLogger(ClientHandler.class);

        private final Service service;

        public ClientHandler(Service service) {
            assert service != null;
            this.service = service;
        }

        @Override
        public void execute(Socket socket) {
            while (!socket.isClosed()){
                try {
                    String line = new BufferedReader(new InputStreamReader(socket.getInputStream())).readLine();
                    if (line == null){
                        LOGGER.warn("No more data available");
                        break;
                    }
                    onMessageReceived(line, socket);
                } catch (IOException e) {
                    LOGGER.warn(String.format("IOException occured: %s", e.getMessage()));
                    break;
                }
                LOGGER.warn("Closing socket connection");
            }
        }
    }

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractService.class);

    private final Server server;
    private final int portNumber;
    private final int clientLimit;
    private final Code onConnection;

    private AtomicReference status = new AtomicReference<>(Status.STOPPED);

    public AbstractService(Port port, int clientLimit) {
        this.server = new Server();
        this.portNumber = port.getNumber();
        this.clientLimit = clientLimit;
        this.onConnection = new ClientHandler(this);
    }

    @Override
    public void start() {
        if (!status.compareAndSet(Status.STOPPED, Status.STARTING)){
            LOGGER.info(String.format("Service is already running on port %d.", portNumber));
            return;
        }
        server.open(portNumber, clientLimit, onConnection);
        status.set(Status.STARTED);
        LOGGER.info(String.format("Service started at port %d.",  portNumber));
    }

    @Override
    public void stop() {
        if (!status.compareAndSet(Status.STARTED, Status.STOPPING)){
            LOGGER.info(String.format("Service at port %d is not running.", portNumber));
            return;
        }
        server.close();
        status.set(Status.STOPPED);
        LOGGER.info(String.format("Service at port %d stopped.", portNumber));
    }

    @Override
    public Status getStatus() {
        return status.get();
    }

    @Override
    public void close() throws Exception {
        stop();
    }

    protected abstract void onMessageReceived(String message, Socket socket);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy