/*
 * 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
<<<<<<< Updated upstream
 *
 *     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
=======
 * 
 *     https://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 
>>>>>>> Stashed changes
 * 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());
    }
  }
}
