/*
 * 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.logging.log4j.core.config.xml;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import javax.xml.XMLConstants;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.mutable.MutableInt;
import org.junit.jupiter.api.Test;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.XMLFilterImpl;
import org.xml.sax.helpers.XMLReaderFactory;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class XmlSchemaTest {

    private static final String TARGET_NAMESPACE = "http://logging.apache.org/log4j/2.0/config";

    private static final List<String> IGNORE_CONFIGS = Arrays.asList( //
            "log4j2-arbiters.xml", // Arbiters violate XML schema as they can appear anywhere
            "log4j2-scriptArbiters.xml",
            "log4j2-selectArbiters.xml",
            "log4j-core-gctests/src/test/resources/gcFreeLogging.xml", // has 2 <Pattern> tags defined
            "legacy-plugins.xml", //
            "logback", // logback configs
            "log4j-xinclude", //
            "log4j12", // log4j 1.x configs
            "perf-CountingNoOpAppender.xml", // uses test-appender CountingNoOp
            "reconfiguration-deadlock.xml", // uses test-appender ReconfigurationDeadlockTestAppender
            "XmlConfigurationSecurity.xml" //
    );

    private static String capitalizeTags(final String xml) {
        final StringBuffer sb = new StringBuffer();
        final Matcher m = Pattern.compile("([<][/]?[a-z])").matcher(xml);
        while (m.find()) {
            m.appendReplacement(sb, m.group(1).toUpperCase());
        }
        return m.appendTail(sb).toString();
    }

    private static String fixXml(String xml) {
        xml = StringUtils.replace(xml, "JSONLayout", "JsonLayout");
        xml = StringUtils.replace(xml, "HTMLLayout", "HtmlLayout");
        xml = StringUtils.replace(xml, "XMLLayout", "XmlLayout");
        xml = StringUtils.replace(xml, "appender-ref", "AppenderRef");
        xml = StringUtils.replace(xml, " onmatch=", " onMatch=");
        xml = StringUtils.replace(xml, " onMisMatch=", " onMismatch=");
        xml = StringUtils.replace(xml, " onmismatch=", " onMismatch=");
        xml = StringUtils.replace(xml, "<Marker ", "<MarkerFilter ");
        xml = StringUtils.replace(xml, " Value=", " value=");
        xml = capitalizeTags(xml);
        return xml;
    }

    @Test
    public void testXmlSchemaValidation() throws SAXException, IOException {
        final SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        final Schema schema = factory.newSchema(new StreamSource(new File("src/main/resources/Log4j-config.xsd")));
        final Validator validator = schema.newValidator();

        final XMLFilterImpl namespaceAdder = new XMLFilterImpl(XMLReaderFactory.createXMLReader()) {
            @Override
            public void startElement(final String namespace, final String localName, final String qName,
                    final Attributes atts) throws SAXException {
                super.startElement(TARGET_NAMESPACE, localName, qName, atts);
            }
        };

        final MutableInt configs = new MutableInt();
        final MutableInt failures = new MutableInt();

        try (final Stream<Path> testResources = Files.list(Paths.get("src", "test", "resources"))) {
            testResources
                    .filter(filePath -> {
                        final String fileName = filePath.getFileName().toString();
                        if (!fileName.endsWith(".xml"))
                            return false;
                        for (final String ignore : IGNORE_CONFIGS) {
                            if (fileName.contains(ignore))
                                return false;
                        }
                        return true;
                    }) //
                    .forEach(filePath -> {
                        System.out.println("Validating " + configs.incrementAndGet() + ". [" + filePath + "]...");
                        System.out.flush();

                        try {
                            final String xml = fixXml(
                                    FileUtils.readFileToString(filePath.toFile(), Charset.defaultCharset()));
                            validator.validate(new SAXSource(namespaceAdder,
                                    new InputSource(new ByteArrayInputStream(xml.getBytes()))), null);
                        } catch (final Exception ex) {
                            System.err.println(ex);
                            System.err.flush();
                            failures.increment();
                        }
                    });
        }

        assertEquals(0, failures.intValue());
    }
}
