/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.log4j.net;

import org.apache.log4j.plugins.Pauseable;
import org.apache.log4j.plugins.Plugin;
import org.apache.log4j.plugins.Receiver;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.spi.LoggingEvent;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;


/**
 * SocketReceiver receives a remote logging event on a configured
 * socket and "posts" it to a LoggerRepository as if the event was
 * generated locally. This class is designed to receive events from
 * the SocketAppender class (or classes that send compatible events).
 * <p>
 * <p>Once the event has been "posted", it will be handled by the
 * appenders currently configured in the LoggerRespository.
 *
 * @author Mark Womack
 * @author Scott Deboy (sdeboy@apache.org)
 * @author Paul Smith (psmith@apache.org)
 */
public class SocketReceiver extends Receiver implements Runnable, PortBased,
    Pauseable {
    /**
     * socket map.
     */
    private Map<Socket, SocketNode13> socketMap = new HashMap<>();
    /**
     * Paused.
     */
    private boolean paused;
    /**
     * Thread.
     */
    private Thread rThread;
    /**
     * Port.
     */
    protected int port;
    /**
     * Server socket.
     */
    private ServerSocket serverSocket;
    /**
     * Socket list.
     */
    private Vector<Socket> socketList = new Vector<>();

    /**
     * The MulticastDNS zone advertised by a SocketReceiver
     */
    public static final String ZONE = "_log4j_obj_tcpaccept_receiver.local.";

    /**
     * Listener.
     */
    private SocketNodeEventListener listener = null;
    /**
     * Listeners.
     */
    private final List listenerList = Collections.synchronizedList(new ArrayList());
    private boolean advertiseViaMulticastDNS;
    private ZeroConfSupport zeroConf;

    /**
     * Create new instance.
     */
    public SocketReceiver() {
        super();
    }

    /**
     * Create new instance.
     *
     * @param p port
     */
    public SocketReceiver(final int p) {
        super();
        port = p;
    }

    /**
     * Create new instance.
     *
     * @param p    port
     * @param repo logger repository
     */
    public SocketReceiver(final int p, final LoggerRepository repo) {
        super();
        this.port = p;
        repository = repo;
    }

    /**
     * {@inheritDoc}
     */
    public int getPort() {
        return port;
    }

    /**
     * {@inheritDoc}
     */
    public void setPort(final int p) {
        port = p;
    }

    /**
     * Returns true if the receiver is the same class and they are
     * configured for the same properties, and super class also considers
     * them to be equivalent. This is used by PluginRegistry when determining
     * if the a similarly configured receiver is being started.
     *
     * @param testPlugin The plugin to test equivalency against.
     * @return boolean True if the testPlugin is equivalent to this plugin.
     */
    public boolean isEquivalent(final Plugin testPlugin) {
        if ((testPlugin != null) && testPlugin instanceof SocketReceiver) {
            SocketReceiver sReceiver = (SocketReceiver) testPlugin;

            return (port == sReceiver.getPort() && super.isEquivalent(testPlugin));
        }

        return false;
    }

    /**
     * Starts the SocketReceiver with the current options.
     */
    public void activateOptions() {
        if (!isActive()) {
            //      shutdown();
            rThread = new Thread(this);
            rThread.setDaemon(true);
            rThread.start();
            if (advertiseViaMulticastDNS) {
                zeroConf = new ZeroConfSupport(ZONE, port, getName());
                zeroConf.advertise();
            }

            active = true;
        }
    }

    /**
     * Called when the receiver should be stopped. Closes the
     * server socket and all of the open sockets.
     */
    public synchronized void shutdown() {
        getLogger().debug(getName() + " received shutdown request");

        // mark this as no longer running
        active = false;

        if (rThread != null) {
            rThread.interrupt();
            rThread = null;
        }
        if (advertiseViaMulticastDNS) {
            zeroConf.unadvertise();
        }

        doShutdown();
    }

    /**
     * Does the actual shutting down by closing the server socket
     * and any connected sockets that have been created.
     */
    private synchronized void doShutdown() {
        active = false;

        getLogger().debug(getName() + " doShutdown called");

        // close the server socket
        closeServerSocket();

        // close all of the accepted sockets
        closeAllAcceptedSockets();
    }

    /**
     * Closes the server socket, if created.
     */
    private void closeServerSocket() {
        getLogger().debug("{} closing server socket", getName());

        try {
            if (serverSocket != null) {
                serverSocket.close();
            }
        } catch (Exception e) {
            // ignore for now
        }

        serverSocket = null;
    }

    /**
     * Closes all the connected sockets in the List.
     */
    private synchronized void closeAllAcceptedSockets() {
        for (Object aSocketList : socketList) {
            try {
                ((Socket) aSocketList).close();
            } catch (Exception e) {
                // ignore for now
            }
        }

        // clear member variables
        socketMap.clear();
        socketList.clear();
    }

    /**
     * Sets the flag to indicate if receiver is active or not.
     *
     * @param b new value
     */
    protected synchronized void setActive(final boolean b) {
        active = b;
    }

    public void setAdvertiseViaMulticastDNS(boolean advertiseViaMulticastDNS) {
        this.advertiseViaMulticastDNS = advertiseViaMulticastDNS;
    }

    public boolean isAdvertiseViaMulticastDNS() {
        return advertiseViaMulticastDNS;
    }

    /**
     * Loop, accepting new socket connections.
     */
    public void run() {
        /**
         * Ensure we start fresh.
         */
        closeServerSocket();
        closeAllAcceptedSockets();

        // start the server socket
        try {
            serverSocket = new ServerSocket(port);
        } catch (Exception e) {
            getLogger().error(
                "error starting SocketReceiver (" + this.getName()
                    + "), receiver did not start", e);
            active = false;

            return;
        }

        Socket socket = null;

        try {
            getLogger().debug("in run-about to enter while not interrupted loop");

            active = true;

            while (!rThread.isInterrupted()) {
                // if we have a socket, start watching it
                if (socket != null) {
                    getLogger().debug(
                        "socket not null - creating and starting socketnode");
                    socketList.add(socket);

                    SocketNode13 node = new SocketNode13(socket, this);
                    synchronized (listenerList) {
                        for (Object aListenerList : listenerList) {
                            SocketNodeEventListener l =
                                (SocketNodeEventListener) aListenerList;
                            node.addSocketNodeEventListener(l);
                        }
                    }
                    socketMap.put(socket, node);
                    new Thread(node).start();
                    socket = null;
                }

                getLogger().debug("waiting to accept socket");

                // wait for a socket to open, then loop to start it
                socket = serverSocket.accept();
                getLogger().debug("accepted socket");
            }
        } catch (Exception e) {
            getLogger().warn(
                "exception while watching socket server in SocketReceiver ("
                    + this.getName() + "), stopping");
        }

        getLogger().debug("{} has exited the not interrupted loop", getName());

        // socket not watched because we a no longer running
        // so close it now.
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e1) {
                getLogger().warn("socket exception caught - socket closed");
            }
        }

        getLogger().debug("{} is exiting main run loop", getName());
    }

    /**
     * Returns a Vector of SocketDetail representing the IP/Domain name
     * of the currently connected sockets that this receiver has
     * been responsible for creating.
     *
     * @return Vector of SocketDetails
     */
    public Vector<SocketDetail> getConnectedSocketDetails() {
        Vector<SocketDetail> details = new Vector<>(socketList.size());

        for (Enumeration<Socket> enumeration = socketList.elements();
             enumeration.hasMoreElements();
            ) {
            Socket socket = enumeration.nextElement();
            details.add(
                new SocketDetail(socket, socketMap.get(socket)));
        }

        return details;
    }

    /**
     * Returns the currently configured SocketNodeEventListener that
     * will be automatically set for each SocketNode created.
     *
     * @return SocketNodeEventListener currently configured
     * @deprecated This receiver now supports multiple listeners
     */
    public SocketNodeEventListener getListener() {
        return listener;
    }

    /**
     * Adds the listener to the list of listeners to be notified of the
     * respective event.
     *
     * @param l the listener to add to the list
     */
    public void addSocketNodeEventListener(
        final SocketNodeEventListener l) {
        listenerList.add(l);
    }

    /**
     * Removes the registered Listener from this instances list of
     * listeners.  If the listener has not been registered, then invoking
     * this method has no effect.
     *
     * @param l the SocketNodeEventListener to remove
     */
    public void removeSocketNodeEventListener(
        final SocketNodeEventListener l) {
        listenerList.remove(l);
    }

    /**
     * Sets the SocketNodeEventListener that will be used for each
     * created SocketNode.
     *
     * @param l the listener to set on each creation of a SocketNode
     * @deprecated This receiver now supports multiple listeners and
     * so this method simply removes the listener (if there already)
     * and readds it to the list.
     * <p>
     * The passed listener will also be returned via the getListener()
     * method still, but this is also deprecated
     */
    public void setListener(final SocketNodeEventListener l) {
        removeSocketNodeEventListener(l);
        addSocketNodeEventListener(l);
        this.listener = l;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isPaused() {
        return paused;
    }

    /**
     * {@inheritDoc}
     */
    public void setPaused(final boolean b) {
        paused = b;
    }

    /**
     * Socket detail.
     */
    private static final class SocketDetail implements AddressBased, PortBased,
        Pauseable {
        /**
         * Address.
         */
        private String address;
        /**
         * Port.
         */
        private int port;
        /**
         * Socket node.
         */
        private SocketNode13 socketNode;

        /**
         * Create new instance.
         *
         * @param socket socket
         * @param node   socket node
         */
        private SocketDetail(final Socket socket,
                             final SocketNode13 node) {
            super();
            this.address = socket.getInetAddress().getHostName();
            this.port = socket.getPort();
            this.socketNode = node;
        }

        /**
         * {@inheritDoc}
         */
        public String getAddress() {
            return address;
        }

        /**
         * {@inheritDoc}
         */
        public int getPort() {
            return port;
        }

        /**
         * {@inheritDoc}
         */
        public String getName() {
            return "Socket";
        }

        /**
         * {@inheritDoc}
         */
        public boolean isActive() {
            return true;
        }

        /**
         * {@inheritDoc}
         */
        public boolean isPaused() {
            return socketNode.isPaused();
        }

        /**
         * {@inheritDoc}
         */
        public void setPaused(final boolean b) {
            socketNode.setPaused(b);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void doPost(final LoggingEvent event) {
        if (!isPaused()) {
            super.doPost(event);
        }
    }

}
