/*
 * 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 javax.jdo.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.jdo.JDOFatalException;
import javax.jdo.JDOFatalInternalException;
import javax.jdo.LegacyJava;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * Tests schema files.
 *
 * <p>
 */
public class XMLTestUtil {

  /** */
  protected static final String BASEDIR = System.getProperty("basedir", ".");

  /** "http://www.w3.org/2001/XMLSchema" */
  protected static final String XSD_TYPE = "http://www.w3.org/2001/XMLSchema";

  /** */
  protected static final String SCHEMA_LANGUAGE_PROP =
      "http://java.sun.com/xml/jaxp/properties/schemaLanguage";

  /** */
  protected static final String SCHEMA_LOCATION_PROP =
      "http://apache.org/xml/properties/schema/external-schemaLocation";

  /** jdo namespace */
  protected static final String JDO_XSD_NS = "https://db.apache.org/jdo/xmlns/jdo";

  /** orm namespace */
  protected static final String ORM_XSD_NS = "https://db.apache.org/jdo/xmlns/orm";

  /** jdoquery namespace */
  protected static final String JDOQUERY_XSD_NS = "https://db.apache.org/jdo/xmlns/jdoquery";

  /** jdo xsd file */
  protected static final File JDO_XSD_FILE =
      new File(BASEDIR + "/target/classes/javax/jdo/jdo_3_2.xsd");

  /** orm xsd file */
  protected static final File ORM_XSD_FILE =
      new File(BASEDIR + "/target/classes/javax/jdo/orm_3_2.xsd");

  /** jdoquery xsd file */
  protected static final File JDOQUERY_XSD_FILE =
      new File(BASEDIR + "/target/classes/javax/jdo/jdoquery_3_2.xsd");

  /** Entity resolver */
  protected static final EntityResolver resolver = new JDOEntityResolver();

  /** Error handler */
  protected static final Handler handler = new Handler();

  /**
   * Name of the metadata property, a comma separated list of JDO metadata file or directories
   * containing such files.
   */
  protected static final String METADATA_PROP = "javax.jdo.metadata";

  /** Name of the recursive property, allowing recursive search of metadata files. */
  protected static final String RECURSIVE_PROP = "javax.jdo.recursive";

  /** Separator character for the metadata property. */
  protected static final String DELIM = ",;";

  /** Newline. */
  protected static final String NL = System.getProperty("line.separator");

  /** XSD builder for jdo namespace. */
  private final DocumentBuilder jdoXsdBuilder =
      createBuilder(JDO_XSD_NS + " " + JDO_XSD_FILE.toURI().toString());

  /** XSD builder for orm namespace. */
  private final DocumentBuilder ormXsdBuilder =
      createBuilder(ORM_XSD_NS + " " + ORM_XSD_FILE.toURI().toString());

  /** XSD builder for jdoquery namespace. */
  private final DocumentBuilder jdoqueryXsdBuilder =
      createBuilder(JDOQUERY_XSD_NS + " " + JDOQUERY_XSD_FILE.toURI().toString());

  /** DTD builder. */
  private final DocumentBuilder dtdBuilder = createBuilder(true);

  /** Non validating builder. */
  private final DocumentBuilder nonValidatingBuilder = createBuilder(false);

  /** Create XSD builder. */
  private DocumentBuilder createBuilder(String location) {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(true);
    factory.setNamespaceAware(true);
    factory.setAttribute(SCHEMA_LANGUAGE_PROP, XSD_TYPE);
    factory.setAttribute(SCHEMA_LOCATION_PROP, location);
    return getParser(factory);
  }

  /** Create builder. */
  private DocumentBuilder createBuilder(boolean validating) {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(validating);
    factory.setNamespaceAware(true);
    return getParser(factory);
  }

  /** Returns a parser obtained from specified factroy. */
  private DocumentBuilder getParser(DocumentBuilderFactory factory) {
    try {
      DocumentBuilder builder = factory.newDocumentBuilder();
      builder.setEntityResolver(resolver);
      builder.setErrorHandler(handler);
      return builder;
    } catch (ParserConfigurationException ex) {
      throw new JDOFatalException("Cannot create XML parser", ex);
    }
  }

  /**
   * Parse the specified files. The valid parameter determines whether the specified files are valid
   * JDO metadata files. The method does not throw an exception on an error, instead it instead it
   * returns the error message(s) as string.
   */
  public String checkXML(File[] files, boolean valid) {
    StringBuffer messages = new StringBuffer();
    for (int i = 0; i < files.length; i++) {
      String msg = checkXML(files[i], valid);
      if (msg != null) {
        messages.append(msg);
      }
    }
    return (messages.length() == 0) ? null : messages.toString();
  }

  /**
   * Parse the specified files using a non validating parser. The method does not throw an exception
   * on an error, instead it instead it returns the error message(s) as string.
   */
  public String checkXMLNonValidating(File[] files) {
    StringBuffer messages = new StringBuffer();
    for (int i = 0; i < files.length; i++) {
      String msg = checkXML(nonValidatingBuilder, files[i], true);
      if (msg != null) {
        messages.append(msg);
      }
    }
    return (messages.length() == 0) ? null : messages.toString();
  }

  /**
   * Parse the specified file. The method checks whether it is a XSD or DTD base file and parses the
   * file using a builder according to the file name suffix. The valid parameter determines whether
   * the specified files are valid JDO metadata files. The method does not throw an exception on an
   * error, instead it returns the error message(s) as string.
   */
  private String checkXML(File file, boolean valid) {
    String messages = null;
    String fileName = file.getName();
    try {
      if (isDTDBased(file)) {
        messages = checkXML(dtdBuilder, file, valid);
      } else if (fileName.endsWith(".jdo")) {
        messages = checkXML(jdoXsdBuilder, file, valid);
      } else if (fileName.endsWith(".orm")) {
        messages = checkXML(ormXsdBuilder, file, valid);
      } else if (fileName.endsWith(".jdoquery")) {
        messages = checkXML(jdoqueryXsdBuilder, file, valid);
      }
    } catch (SAXException ex) {
      messages = ex.getMessage();
    }
    return messages;
  }

  /**
   * Parse the specified file using the specified builder. The valid parameter determines whether
   * the specified files are valid JDO metadata files. The method does not throw an exception on an
   * error, instead it returns the error message(s) as string.
   */
  private String checkXML(DocumentBuilder builder, File file, boolean valid) {
    String messages = null;
    handler.init(file);
    try {
      builder.parse(file);
    } catch (SAXParseException ex) {
      handler.error(ex);
    } catch (Exception ex) {
      messages = "Fatal error processing " + file.getName() + ":  " + ex + NL;
    }
    if (messages == null) {
      messages = handler.getMessages();
    }
    if (!valid) {
      if (messages != null) {
        // expected error for negative test
        messages = null;
      } else {
        messages = file.getName() + " is not valid, " + "but the parser did not catch the error.";
      }
    }
    return messages;
  }

  /**
   * Checks whether the specifeid file is DTD or XSD based. The method throws a SAXException if the
   * file has syntax errors.
   */
  private boolean isDTDBased(File file) throws SAXException {
    handler.init(file);
    try {
      Document document = nonValidatingBuilder.parse(file);
      return document.getDoctype() != null;
    } catch (SAXParseException ex) {
      handler.error(ex);
      throw new SAXException(handler.getMessages());
    } catch (Exception ex) {
      throw new SAXException("Fatal error processing " + file.getName() + ":  " + ex);
    }
  }

  /** ErrorHandler implementation. */
  private static class Handler implements ErrorHandler {

    private File fileUnderTest;
    private String[] lines;
    private StringBuffer messages;

    public void error(SAXParseException ex) {
      append("Handler.error: ", ex);
    }

    public void fatalError(SAXParseException ex) {
      append("Handler.fatalError: ", ex);
    }

    public void warning(SAXParseException ex) {
      append("Handler.warning: ", ex);
    }

    public void init(File file) {
      this.fileUnderTest = file;
      this.messages = new StringBuffer();
      this.lines = null;
    }

    public String getMessages() {
      return (messages.length() == 0) ? null : messages.toString();
    }

    private void append(String prefix, SAXParseException ex) {
      int lineNumber = ex.getLineNumber();
      int columnNumber = ex.getColumnNumber();
      messages.append("------------------------").append(NL);
      messages.append(prefix).append(fileUnderTest.getName());
      messages.append(" [line=").append(lineNumber);
      messages.append(", col=").append(columnNumber).append("]: ");
      messages.append(ex.getMessage()).append(NL);
      messages.append(getErrorLocation(lineNumber, columnNumber));
    }

    private String[] getLines() {
      if (lines == null) {
        try {
          BufferedReader bufferedReader = new BufferedReader(new FileReader(fileUnderTest));
          ArrayList<String> tmp = new ArrayList<>();
          while (bufferedReader.ready()) {
            tmp.add(bufferedReader.readLine());
          }
          lines = tmp.toArray(new String[tmp.size()]);
        } catch (IOException ex) {
          throw new JDOFatalException("getLines: caught IOException", ex);
        }
      }
      return lines;
    }

    /** Return the error location for the file under test. */
    private String getErrorLocation(int lineNumber, int columnNumber) {
      String[] lines = getLines();
      int length = lines.length;
      if (lineNumber > length) {
        return "Line number "
            + lineNumber
            + " exceeds the number of lines in the file ("
            + lines.length
            + ")";
      } else if (lineNumber < 1) {
        return "Line number " + lineNumber + " does not allow retriving the error location.";
      }
      StringBuffer buf = new StringBuffer();
      if (lineNumber > 2) {
        buf.append(lines[lineNumber - 3]);
        buf.append(NL);
        buf.append(lines[lineNumber - 2]);
        buf.append(NL);
      }
      buf.append(lines[lineNumber - 1]);
      buf.append(NL);
      for (int i = 1; i < columnNumber; ++i) {
        buf.append(' ');
      }
      buf.append("^\n");
      if (lineNumber + 1 < length) {
        buf.append(lines[lineNumber]);
        buf.append(NL);
        buf.append(lines[lineNumber + 1]);
        buf.append(NL);
      }
      return buf.toString();
    }
  }

  /**
   * Implementation of EntityResolver interface to check the jdo.dtd location. TODO Somebody should
   * update these 2.2 to 3.1 or later at some point.
   */
  private static class JDOEntityResolver implements EntityResolver {

    private static final String RECOGNIZED_JDO_PUBLIC_ID =
        "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 3.2//EN";
    private static final String RECOGNIZED_JDO_SYSTEM_ID = "file:/javax/jdo/jdo_3_2.dtd";
    private static final String RECOGNIZED_JDO_SYSTEM_ID2 = "http://xmlns.jcp.org/dtd/jdo_3_2.dtd";
    private static final String RECOGNIZED_ORM_PUBLIC_ID =
        "-//Sun Microsystems, Inc.//DTD Java Data Objects Mapping Metadata 3.2//EN";
    private static final String RECOGNIZED_ORM_SYSTEM_ID = "file:/javax/jdo/orm_3_2.dtd";
    private static final String RECOGNIZED_ORM_SYSTEM_ID2 = "http://xmlns.jcp.org/dtd/orm_3_2.dtd";
    private static final String RECOGNIZED_JDOQUERY_PUBLIC_ID =
        "-//Sun Microsystems, Inc.//DTD Java Data Objects Query Metadata 3.2//EN";
    private static final String RECOGNIZED_JDOQUERY_SYSTEM_ID = "file:/javax/jdo/jdoquery_3_2.dtd";
    private static final String RECOGNIZED_JDOQUERY_SYSTEM_ID2 =
        "http://xmlns.jcp.org/dtd/jdoquery_3_2.dtd";
    private static final String JDO_DTD_FILENAME = "javax/jdo/jdo_3_2.dtd";
    private static final String ORM_DTD_FILENAME = "javax/jdo/orm_3_2.dtd";
    private static final String JDOQUERY_DTD_FILENAME = "javax/jdo/jdoquery_3_2.dtd";

    static final Map<String, String> publicIds = new HashMap<>();
    static final Map<String, String> systemIds = new HashMap<>();

    static {
      publicIds.put(RECOGNIZED_JDO_PUBLIC_ID, JDO_DTD_FILENAME);
      publicIds.put(RECOGNIZED_ORM_PUBLIC_ID, ORM_DTD_FILENAME);
      publicIds.put(RECOGNIZED_JDOQUERY_PUBLIC_ID, JDOQUERY_DTD_FILENAME);
      systemIds.put(RECOGNIZED_JDO_SYSTEM_ID, JDO_DTD_FILENAME);
      systemIds.put(RECOGNIZED_ORM_SYSTEM_ID, ORM_DTD_FILENAME);
      systemIds.put(RECOGNIZED_JDOQUERY_SYSTEM_ID, JDOQUERY_DTD_FILENAME);
      systemIds.put(RECOGNIZED_JDO_SYSTEM_ID2, JDO_DTD_FILENAME);
      systemIds.put(RECOGNIZED_ORM_SYSTEM_ID2, ORM_DTD_FILENAME);
      systemIds.put(RECOGNIZED_JDOQUERY_SYSTEM_ID2, JDOQUERY_DTD_FILENAME);
    }

    public InputSource resolveEntity(String publicId, final String systemId)
        throws SAXException, IOException {
      // check for recognized ids
      String filename = publicIds.get(publicId);
      if (filename == null) {
        filename = systemIds.get(systemId);
      }
      final String finalName = filename;
      if (finalName == null) {
        return null;
      } else {
        // Substitute the dtd with the one from javax.jdo.jdo.dtd,
        // but only if the publicId is equal to RECOGNIZED_PUBLIC_ID
        // or there is no publicID and the systemID is equal to
        // RECOGNIZED_SYSTEM_ID.
        InputStream stream =
            doPrivileged(
                new PrivilegedAction<InputStream>() {
                  public InputStream run() {
                    return getClass().getClassLoader().getResourceAsStream(finalName);
                  }
                });
        if (stream == null) {
          throw new JDOFatalException(
              "Cannot load "
                  + finalName
                  + ", because the file does not exist in the jdo.jar file, "
                  + "or the JDOParser class is not granted permission to read this file.  "
                  + "The metadata .xml file contained PUBLIC="
                  + publicId
                  + " SYSTEM="
                  + systemId
                  + ".");
        }
        return new InputSource(new InputStreamReader(stream));
      }
    }
  }

  /** Helper class to find all test JDO metadata files. */
  public static class XMLFinder {

    private final List<File> metadataFiles = new ArrayList<>();
    private final boolean recursive;

    /** Constructor. */
    public XMLFinder(String[] fileNames, boolean recursive) {
      this.recursive = recursive;
      if (fileNames == null) return;
      for (int i = 0; i < fileNames.length; i++) {
        appendTestFiles(fileNames[i]);
      }
    }

    /** Returns array of files of matching file names. */
    private File[] getFiles(File dir, final String suffix) {
      FilenameFilter filter = (file, name) -> name.endsWith(suffix);
      return dir.listFiles(filter);
    }

    /** */
    private File[] getDirectories(File dir) {
      FileFilter filter = File::isDirectory;
      return dir.listFiles(filter);
    }

    /** */
    private void appendTestFiles(String fileName) {
      File file = new File(fileName);
      if (file.isDirectory()) {
        processDirectory(file);
      } else if (fileName.endsWith(".jdo")
          || fileName.endsWith(".orm")
          || fileName.endsWith(".jdoquery")) {
        metadataFiles.add(new File(fileName));
      }
    }

    /**
     * Adds all files with suffix .jdo, .orm and .jdoquery to the list of metadata files.
     * Recursively process subdirectories if recursive flag is set.
     */
    private void processDirectory(File dir) {
      metadataFiles.addAll(Arrays.asList(getFiles(dir, ".jdo")));
      metadataFiles.addAll(Arrays.asList(getFiles(dir, ".orm")));
      metadataFiles.addAll(Arrays.asList(getFiles(dir, ".jdoquery")));
      if (recursive) {
        File[] subdirs = getDirectories(dir);
        for (int i = 0; i < subdirs.length; i++) {
          processDirectory(subdirs[i]);
        }
      }
    }

    /** Returns an array of test files with suffix .jdo, .orm or .jdoquery. */
    public File[] getMetadataFiles() {
      return metadataFiles.toArray(new File[metadataFiles.size()]);
    }
  }

  /** */
  private static String[] checkMetadataSystemProperty() {
    String[] ret = null;
    String metadata = System.getProperty(METADATA_PROP);
    if ((metadata != null) && (metadata.length() > 0)) {
      List<String> entries = new ArrayList<>();
      StringTokenizer st = new StringTokenizer(metadata, DELIM);
      while (st.hasMoreTokens()) {
        entries.add(st.nextToken());
      }
      ret = entries.toArray(new String[entries.size()]);
    }
    return ret;
  }

  /** Command line tool to test JDO metadata files. Usage: XMLTestUtil [-r] <file or directory>+ */
  public static void main(String args[]) {
    String[] fromProp = checkMetadataSystemProperty();
    boolean recursive = Boolean.getBoolean(RECURSIVE_PROP);

    // handle command line args
    String[] fileNames = null;
    if ((args.length > 0) && ("-r".equals(args[0]))) {
      recursive = true;
      fileNames = new String[args.length - 1];
      System.arraycopy(args, 1, fileNames, 0, args.length - 1);
    } else {
      fileNames = args;
    }

    // check args
    if ((fileNames.length == 0) && (fromProp == null)) {
      System.err.println(
          "No commandline arguments and system property metadata not defined; "
              + "nothing to be tested.\nUsage: XMLTestUtil [-r] <directories>\n"
              + "\tAll .jdo, .orm, and .jdoquery files in the directory (recursively) will be tested.");
    } else if ((fileNames.length == 0) && (fromProp != null)) {
      // use metadata system property
      fileNames = fromProp;
    } else if ((fileNames.length != 0) && (fromProp != null)) {
      System.err.println(
          "Commandline arguments specified and system property metadata defined; "
              + "ignoring system property metadata.");
    }

    // run the test
    XMLTestUtil xmlTest = new XMLTestUtil();
    File[] files = new XMLFinder(fileNames, recursive).getMetadataFiles();
    for (int i = 0; i < files.length; i++) {
      File file = files[i];
      System.out.print("Checking " + file.getPath() + ": ");
      String messages = xmlTest.checkXML(file, true);
      messages = (messages == null) ? "OK" : NL + messages;
      System.out.println(messages);
    }
  }

  @SuppressWarnings("unchecked")
  private static <T> T doPrivileged(PrivilegedAction<T> privilegedAction) {
    try {
      return (T) LegacyJava.doPrivilegedAction.invoke(null, privilegedAction);
    } catch (IllegalAccessException | InvocationTargetException e) {
      if (e.getCause() instanceof RuntimeException) {
        throw (RuntimeException) e.getCause();
      }
      throw new JDOFatalInternalException(e.getMessage());
    }
  }
}
