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

import java.awt.Component;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;
import java.util.zip.ZipInputStream;

import javax.swing.ProgressMonitorInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.UtilLoggingLevel;
import org.apache.log4j.spi.Decoder;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.apache.log4j.spi.LocationInfo;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;


/**
 * Decodes JDK 1.4's java.util.logging package events
 * delivered via XML (using the logger.dtd).
 *
 * @author Scott Deboy (sdeboy@apache.org)
 * @author Paul Smith (psmith@apache.org)
 *
 */
public class UtilLoggingXMLDecoder implements Decoder {
  //NOTE: xml section is only handed on first delivery of events
  //on this first delivery of events, there is no end tag for the log element
  /**
   * Document prolog.
   */
  private static final String BEGIN_PART =
    "<log>";
    /**
     * Document close.
     */
  private static final String END_PART = "</log>";
    /**
     * Document builder.
     */
  private DocumentBuilder docBuilder;
    /**
     * Additional properties.
     */
  private Map additionalProperties = new HashMap();
    /**
     * Partial event.
     */
  private String partialEvent;
    /**
     * Record end.
     */
  private static final String RECORD_END = "</record>";
    /**
     * Owner.
     */
  private Component owner = null;

  private static final String ENCODING = "UTF-8";

    /**
     * Create new instance.
     * @param o owner
     */
  public UtilLoggingXMLDecoder(final Component o) {
      this();
      this.owner = o;
  }

    /**
     * Create new instance.
     */
  public UtilLoggingXMLDecoder() {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setValidating(false);

    try {
      docBuilder = dbf.newDocumentBuilder();
      docBuilder.setErrorHandler(new SAXErrorHandler());
      docBuilder.setEntityResolver(new UtilLoggingEntityResolver());
    } catch (ParserConfigurationException pce) {
      System.err.println("Unable to get document builder");
    }
  }

  /**
   * Sets an additionalProperty map, where each Key/Value pair is
   * automatically added to each LoggingEvent as it is decoded.
   *
   * This is useful, say, to include the source file name of the Logging events
   * @param properties additional properties
   */
  public void setAdditionalProperties(final Map properties) {
    this.additionalProperties = properties;
  }

  /**
   * Converts the LoggingEvent data in XML string format into an actual
   * XML Document class instance.
   * @param data XML fragment
   * @return  dom document
   */
  private Document parse(final String data) {
    if (docBuilder == null || data == null) {
      return null;
    }

    Document document = null;

    try {
      // we change the system ID to a valid URI so that Crimson won't
      // complain. Indeed, "log4j.dtd" alone is not a valid URI which
      // causes Crimson to barf. The Log4jEntityResolver only cares
      // about the "log4j.dtd" ending.

      /**
       * resetting the length of the StringBuffer is dangerous, particularly
       * on some JDK 1.4 impls, there's a known Bug that causes a memory leak
       */
      StringBuilder buf = new StringBuilder(1024);

      if (!data.startsWith("<?xml")) {
        buf.append(BEGIN_PART);
      }

      buf.append(data);

      if (!data.endsWith(END_PART)) {
        buf.append(END_PART);
      }

      InputSource inputSource =
        new InputSource(new StringReader(buf.toString()));
      document = docBuilder.parse(inputSource);
    } catch (Exception e) {
      e.printStackTrace();
    }

    return document;
  }

  /**
   * Decodes a File into a Vector of LoggingEvents.
   * @param url the url of a file containing events to decode
   * @return Vector of LoggingEvents
   * @throws IOException if IO error during processing.
   */
  public Vector<LoggingEvent> decode(final URL url) throws IOException {
    LineNumberReader reader;
    boolean isZipFile = url.getPath().toLowerCase().endsWith(".zip");
    InputStream inputStream;
    if (isZipFile) {
        inputStream = new ZipInputStream(url.openStream());
        //move stream to next entry so we can read it
        ((ZipInputStream)inputStream).getNextEntry();
    } else {
        inputStream = url.openStream();
    }
    if (owner != null) {
        reader = new LineNumberReader(
                new InputStreamReader(
                        new ProgressMonitorInputStream(owner,
                                "Loading " + url , inputStream), ENCODING));
    } else {
        reader = new LineNumberReader(new InputStreamReader(inputStream, ENCODING));
    }
    Vector<LoggingEvent> v = new Vector<>();

      String line;
      Vector<LoggingEvent> events;
      try {
          while ((line = reader.readLine()) != null) {
              StringBuilder buffer = new StringBuilder(line);
              for (int i = 0; i < 1000; i++) {
                  buffer.append(reader.readLine()).append("\n");
              }
              events = decodeEvents(buffer.toString());
              if (events != null) {
                  v.addAll(events);
              }
          }
    } finally {
      partialEvent = null;
      try {
        if (reader != null) {
          reader.close();
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    return v;
  }

  /**
   * Decodes a String representing a number of events into a
   * Vector of LoggingEvents.
   * @param document to decode events from
   * @return Vector of LoggingEvents
   */
  public Vector<LoggingEvent> decodeEvents(final String document) {

      if (document != null) {

          if (document.trim().equals("")) {
              return null;
          }

          String newDoc;
          String newPartialEvent = null;
          //separate the string into the last portion ending with </record>
          // (which will be processed) and the partial event which
          // will be combined and processed in the next section

          //if the document does not contain a record end,
          // append it to the partial event string
          if (document.lastIndexOf(RECORD_END) == -1) {
              partialEvent = partialEvent + document;
              return null;
          }

          if (document.lastIndexOf(RECORD_END) + RECORD_END.length()
                  < document.length()) {
              newDoc = document.substring(0,
                      document.lastIndexOf(RECORD_END) + RECORD_END.length());
              newPartialEvent = document.substring(
                      document.lastIndexOf(RECORD_END) + RECORD_END.length());
          } else {
              newDoc = document;
          }
          if (partialEvent != null) {
              newDoc = partialEvent + newDoc;
          }
          partialEvent = newPartialEvent;

          Document doc = parse(newDoc);
          if (doc == null) {
              return null;
          }
          return decodeEvents(doc);
      }
      return null;
  }

    /**
      * Converts the string data into an XML Document, and then soaks out the
      * relevant bits to form a new LoggingEvent instance which can be used
      * by any Log4j element locally.
      * @param data XML fragment
      * @return a single LoggingEvent or null
      */
  public LoggingEvent decode(final String data) {
    Document document = parse(data);

    if (document == null) {
      return null;
    }

    Vector<LoggingEvent> events = decodeEvents(document);

    if (events.size() > 0) {
      return events.firstElement();
    }

    return null;
  }

  /**
   * Given a Document, converts the XML into a Vector of LoggingEvents.
   * @param document XML document
   * @return Vector of LoggingEvents
   */
  private Vector<LoggingEvent> decodeEvents(final Document document) {
    Vector<LoggingEvent> events = new Vector<>();

    NodeList eventList = document.getElementsByTagName("record");

    for (int eventIndex = 0; eventIndex < eventList.getLength();
        eventIndex++) {
      Node eventNode = eventList.item(eventIndex);

      Logger logger = null;
    long timeStamp = 0L;
    Level level = null;
    String threadName = null;
    Object message = null;
    String ndc = null;
    String[] exception = null;
    String className = null;
    String methodName = null;
    String fileName = null;
    String lineNumber = null;
    Hashtable properties = new Hashtable();

      //format of date: 2003-05-04T11:04:52
      //ignore date or set as a property? using millis in constructor instead
      NodeList list = eventNode.getChildNodes();
      int listLength = list.getLength();

      if (listLength == 0) {
        continue;
      }

      for (int y = 0; y < listLength; y++) {
        String tagName = list.item(y).getNodeName();

        if (tagName.equalsIgnoreCase("logger")) {
          logger = Logger.getLogger(getCData(list.item(y)));
        }

        if (tagName.equalsIgnoreCase("millis")) {
          timeStamp = Long.parseLong(getCData(list.item(y)));
        }

        if (tagName.equalsIgnoreCase("level")) {
          level = UtilLoggingLevel.toLevel(getCData(list.item(y)));
        }

        if (tagName.equalsIgnoreCase("thread")) {
          threadName = getCData(list.item(y));
        }

        if (tagName.equalsIgnoreCase("sequence")) {
          properties.put("log4jid", getCData(list.item(y)));
        }

        if (tagName.equalsIgnoreCase("message")) {
          message = getCData(list.item(y));
        }

        if (tagName.equalsIgnoreCase("class")) {
          className = getCData(list.item(y));
        }

        if (tagName.equalsIgnoreCase("method")) {
          methodName = getCData(list.item(y));
        }

        if (tagName.equalsIgnoreCase("exception")) {
          ArrayList<String> exceptionList = new ArrayList<>();
          NodeList exList = list.item(y).getChildNodes();
          int exlistLength = exList.getLength();

          for (int i2 = 0; i2 < exlistLength; i2++) {
            Node exNode = exList.item(i2);
            String exName = exList.item(i2).getNodeName();

            if (exName.equalsIgnoreCase("message")) {
              exceptionList.add(getCData(exList.item(i2)));
            }

            if (exName.equalsIgnoreCase("frame")) {
              NodeList exList2 = exNode.getChildNodes();
              int exlist2Length = exList2.getLength();

              for (int i3 = 0; i3 < exlist2Length; i3++) {
                exceptionList.add(getCData(exList2.item(i3)) + "\n");
              }
            }
          }
          if (exceptionList.size() > 0) {
              exception =
                (String[]) exceptionList.toArray(new String[exceptionList.size()]);
          }
        }
      }

        /**
         * We add all the additional properties to the properties
         * hashtable. Override properties that already exist
         */
        if (additionalProperties.size() > 0) {
            if (properties == null) {
                properties = new Hashtable(additionalProperties);
            }
            for (Object o : additionalProperties.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                properties.put(e.getKey(), e.getValue());
            }
        }

      LocationInfo info;
      if ((fileName != null)
              || (className != null)
              || (methodName != null)
              || (lineNumber != null)) {
          info = new LocationInfo(fileName, className, methodName, lineNumber);
      } else {
        info = LocationInfo.NA_LOCATION_INFO;
      }

        ThrowableInformation throwableInfo = null;
        if (exception != null) {
            throwableInfo = new ThrowableInformation(exception);
        }

        LoggingEvent loggingEvent = new LoggingEvent(null,
                logger, timeStamp, level, message,
                threadName,
                throwableInfo,
                ndc,
                info,
                properties);

      events.add(loggingEvent);

    }
    return events;
  }

    /**
     * Get contents of CDATASection.
     * @param n CDATASection
     * @return text content of all text or CDATA children of node.
     */
  private String getCData(final Node n) {
    StringBuilder buf = new StringBuilder();
    NodeList nl = n.getChildNodes();

    for (int x = 0; x < nl.getLength(); x++) {
      Node innerNode = nl.item(x);

      if (
        (innerNode.getNodeType() == Node.TEXT_NODE)
          || (innerNode.getNodeType() == Node.CDATA_SECTION_NODE)) {
        buf.append(innerNode.getNodeValue());
      }
    }

    return buf.toString();
  }
}
