/*
 * 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 java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

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;


/**
  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>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.
   *
   * 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);
    }
  }

}
