/*
 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */


import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public abstract class AbstractConnectionHandler implements Runnable {

    public final static Logger logger = Logger.getGlobal();

    private Socket socket;
    private List<ConnectionChecker> connectionCheckers;
    private List<DataChecker> socks4DataCheckers;

    public AbstractConnectionHandler(Socket socket) {
        this.socket = socket;
        connectionCheckers = new ArrayList<>();
        socks4DataCheckers = new ArrayList<>();
    }

    protected boolean checkConnection(InetAddress ip, int portNumber) throws Socks4Exception {
        for (ConnectionChecker connectionChecker : connectionCheckers) {
            if (!connectionChecker.check(ip, portNumber)) {
                return false;
            }
        }

        return true;
    }

    public void addConnectionChecker(ConnectionChecker connectionChecker) {
        connectionCheckers.add(connectionChecker);
    }

    public void setConnectionCheckers(List<ConnectionChecker> connectionCheckers) {
        this.connectionCheckers = connectionCheckers;
    }

    public void addDataChecker(DataChecker socks4DataChecker) {
        socks4DataCheckers.add(socks4DataChecker);
    }

    public void setDataCheckers(List<DataChecker> socks4DataCheckers) {
        this.socks4DataCheckers = socks4DataCheckers;
    }

    @Override
    public void run() {
        try {
            handleConnection(socket);
            socket.close();
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Got Exception", e);
        }
    }

    protected boolean checkData(byte[] data) {
        for (DataChecker socks4DataChecker : socks4DataCheckers) {
            if (!socks4DataChecker.checkData(data)) {
                return false;
            }
        }

        return true;
    }

    protected abstract void handleConnection(Socket socket) throws Exception;
}
