/*
 * 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.Iterator;
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.logging.log4j.core.LogEvent;


/**
  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 socketMap = new HashMap();
    /**
     * Paused.
     */
  private boolean paused;
    /**
     * Thread.
     */
  private Thread rThread;
    /**
     * Port.
     */
  protected int port;
    /**
     * Server socket.
     */
  private ServerSocket serverSocket;
    /**
     * Socket list.
     */
  private Vector 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 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 (int x = 0; x < socketList.size(); x++) {
      try {
        ((Socket) socketList.get(x)).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 (Iterator iter = listenerList.iterator();
                 iter.hasNext();) {
                SocketNodeEventListener l =
                        (SocketNodeEventListener) iter.next();
                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 getConnectedSocketDetails() {
    Vector details = new Vector(socketList.size());

    for (Enumeration enumeration = socketList.elements();
         enumeration.hasMoreElements();
            ) {
      Socket socket = (Socket) enumeration.nextElement();
      details.add(
        new SocketDetail(socket, (SocketNode13) 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 LogEvent event) {
    if (!isPaused()) {
      super.doPost(event);
    }
  }

}
