/*
 *  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
 *
 *      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
 *  limitations under the License.
 *
 */

package org.apache.tools.ant.taskdefs.optional;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.XSLTLiaison4;
import org.apache.tools.ant.taskdefs.XSLTLogger;
import org.apache.tools.ant.taskdefs.XSLTLoggerAware;
import org.apache.tools.ant.taskdefs.XSLTProcess;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.XMLCatalog;
import org.apache.tools.ant.types.resources.FileProvider;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.URLProvider;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.JAXPUtils;
import org.apache.tools.ant.util.JavaEnvUtils;
import org.apache.tools.ant.util.StreamUtils;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

/**
 * Concrete liaison for XSLT processor implementing TraX. (ie JAXP 1.1)
 *
 * @since Ant 1.3
 */
public class TraXLiaison implements XSLTLiaison4, ErrorListener, XSLTLoggerAware {

    /**
     * Helper for transforming filenames to URIs.
     *
     * @since Ant 1.7
     */
    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();

    /**
     * The current <code>Project</code>
     */
    private Project project;

    /**
     * the name of the factory implementation class to use
     * or null for default JAXP lookup.
     */
    private String factoryName = null;

    /** The trax TransformerFactory */
    private TransformerFactory tfactory = null;

    /** stylesheet to use for transformation */
    private Resource stylesheet;

    private XSLTLogger logger;

    /** possible resolver for publicIds */
    private EntityResolver entityResolver;

    /** transformer to use for processing files */
    private Transformer transformer;

    /** The In memory version of the stylesheet */
    private Templates templates;

    /**
     * The modification time of the stylesheet from which the templates
     * are read
     */
    private long templatesModTime;

    /** possible resolver for URIs */
    private URIResolver uriResolver;

    /** transformer output properties */
    private final Vector<String[]> outputProperties = new Vector<>();

    /** stylesheet parameters */
    private final Hashtable<String, Object> params = new Hashtable<>();

    /** factory attributes */
    private final List<Object[]> attributes = new ArrayList<>();

    /** factory features */
    private final Map<String, Boolean> features = new HashMap<>();

    /** whether to suppress warnings */
    private boolean suppressWarnings = false;

    /** optional trace configuration. */
    private XSLTProcess.TraceConfiguration traceConfiguration = null;

    /**
     * Constructor for TraXLiaison.
     * @throws Exception never
     */
    public TraXLiaison() throws Exception { //NOSONAR
    }

    /**
     * Set the stylesheet file.
     * @param stylesheet a <code>File</code> value
     * @throws Exception on error
     */
    public void setStylesheet(final File stylesheet) throws Exception {
        final FileResource fr = new FileResource();
        fr.setProject(project);
        fr.setFile(stylesheet);
        setStylesheet(fr);
    }

    /**
     * Set the stylesheet file.
     * @param stylesheet a {@link org.apache.tools.ant.types.Resource} value
     * @throws Exception on error
     */
    public void setStylesheet(final Resource stylesheet) throws Exception {
        if (this.stylesheet != null) {
            // resetting the stylesheet - reset transformer
            transformer = null;

            // do we need to reset templates as well
            if (!this.stylesheet.equals(stylesheet)
                || (stylesheet.getLastModified() != templatesModTime)) {
                templates = null;
            }
        }
        this.stylesheet = stylesheet;
    }

    /**
     * Transform an input file.
     * @param infile the file to transform
     * @param outfile the result file
     * @throws Exception on error
     */
    public void transform(final File infile, final File outfile) throws Exception {
        if (transformer == null) {
            createTransformer();
        }

        // autoclose all handles, otherwise the garbage collector will close them...
        // and Windows may complain about not being able to delete files.
        try (InputStream fis = new BufferedInputStream(Files.newInputStream(infile.toPath()));
             OutputStream fos = new BufferedOutputStream(Files.newOutputStream(outfile.toPath()))) {
            final StreamResult res = new StreamResult(fos);
            // not sure what could be the need of this...
            res.setSystemId(JAXPUtils.getSystemId(outfile));
            // set parameters on each transformation, maybe something has changed
            //(e.g. value of file name parameter)
            setTransformationParameters();

            transformer.transform(getSource(fis, infile), res);
        }
    }

    /**
     * Get the source instance from the stream and id of the file.
     * @param is the stream containing the stylesheet data.
     * @param infile the file that will be used for the systemid.
     * @return the configured source instance matching the stylesheet.
     * @throws ParserConfigurationException if a parser cannot be created which
     * satisfies the requested configuration.
     * @throws SAXException in case of problem detected by the SAX parser.
     */
    private Source getSource(final InputStream is, final File infile)
        throws ParserConfigurationException, SAXException {
        // todo: is this comment still relevant ??
        // FIXME: need to use a SAXSource as the source for the transform
        // so we can plug in our own entity resolver
        Source src = null;
        if (entityResolver != null) {
            if (getFactory().getFeature(SAXSource.FEATURE)) {
                final SAXParserFactory spFactory = SAXParserFactory.newInstance();
                spFactory.setNamespaceAware(true);
                final XMLReader reader = spFactory.newSAXParser().getXMLReader();
                reader.setEntityResolver(entityResolver);
                src = new SAXSource(reader, new InputSource(is));
            } else {
                throw new IllegalStateException("xcatalog specified, but "
                    + "parser doesn't support SAX");
            }
        } else {
            // WARN: Don't use the StreamSource(File) ctor. It won't work with
            // xalan prior to 2.2 because of systemid bugs.
            src = new StreamSource(is);
        }
        src.setSystemId(JAXPUtils.getSystemId(infile));
        return src;
    }

    private Source getSource(final InputStream is, final Resource resource)
        throws ParserConfigurationException, SAXException {
        // todo: is this comment still relevant ??
        // FIXME: need to use a SAXSource as the source for the transform
        // so we can plug in our own entity resolver
        Source src = null;
        if (entityResolver != null) {
            if (getFactory().getFeature(SAXSource.FEATURE)) {
                final SAXParserFactory spFactory = SAXParserFactory.newInstance();
                spFactory.setNamespaceAware(true);
                final XMLReader reader = spFactory.newSAXParser().getXMLReader();
                reader.setEntityResolver(entityResolver);
                src = new SAXSource(reader, new InputSource(is));
            } else {
                throw new IllegalStateException("xcatalog specified, but "
                    + "parser doesn't support SAX");
            }
        } else {
            // WARN: Don't use the StreamSource(File) ctor. It won't work with
            // xalan prior to 2.2 because of systemid bugs.
            src = new StreamSource(is);
        }
        // The line below is a hack: the system id must an URI, but it is not
        // cleat to get the URI of an resource, so just set the name of the
        // resource as a system id
        src.setSystemId(resourceToURI(resource));
        return src;
    }

    private String resourceToURI(final Resource resource) {
        final FileProvider fp = resource.as(FileProvider.class);
        if (fp != null) {
            return FILE_UTILS.toURI(fp.getFile().getAbsolutePath());
        }
        final URLProvider up = resource.as(URLProvider.class);
        if (up != null) {
            final URL u = up.getURL();
            return String.valueOf(u);
        } else {
            return resource.getName();
        }
    }

    /**
     * Read in templates from the stylesheet
     */
    private void readTemplates()
        throws IOException, TransformerConfigurationException,
               ParserConfigurationException, SAXException {

        // Use a stream so that you can close it yourself quickly
        // and avoid keeping the handle until the object is garbaged.
        // (always keep control), otherwise you won't be able to delete
        // the file quickly on windows.
        try (InputStream xslStream =
             new BufferedInputStream(stylesheet.getInputStream())) {
            templatesModTime = stylesheet.getLastModified();
            final Source src = getSource(xslStream, stylesheet);
            templates = getFactory().newTemplates(src);
        }
    }

    /**
     * Create a new transformer based on the liaison settings
     * @see #setStylesheet(java.io.File)
     * @see #addParam(java.lang.String, java.lang.String)
     * @see #setOutputProperty(java.lang.String, java.lang.String)
     */
    private void createTransformer()
        throws IOException, ParserConfigurationException, SAXException, TransformerException {
        if (templates == null) {
            readTemplates();
        }

        transformer = templates.newTransformer();

        // configure the transformer...
        transformer.setErrorListener(this);
        if (uriResolver != null) {
            transformer.setURIResolver(uriResolver);
        }
        for (final String[] pair : outputProperties) {
            transformer.setOutputProperty(pair[0], pair[1]);
        }

        if (traceConfiguration != null) {
            if ("org.apache.xalan.transformer.TransformerImpl" //NOSONAR
                .equals(transformer.getClass().getName())) {
                try {
                    final Class<?> traceSupport =
                        Class.forName("org.apache.tools.ant.taskdefs.optional."
                                      + "Xalan2TraceSupport", true,
                                      Thread.currentThread()
                                      .getContextClassLoader());
                    final XSLTTraceSupport ts =
                        (XSLTTraceSupport) traceSupport.getDeclaredConstructor().newInstance();
                    ts.configureTrace(transformer, traceConfiguration);
                } catch (final Exception e) {
                    final String msg = "Failed to enable tracing because of " + e;
                    if (project != null) {
                        project.log(msg, Project.MSG_WARN);
                    } else {
                        System.err.println(msg);
                    }
                }
            } else {
                final String msg = "Not enabling trace support for transformer"
                    + " implementation" + transformer.getClass().getName();
                if (project != null) {
                    project.log(msg, Project.MSG_WARN);
                } else {
                    System.err.println(msg);
                }
            }
        }
    }

    /**
     * Sets the parameters for the transformer.
     */
    private void setTransformationParameters() {
        params.forEach((key, value) -> transformer.setParameter(key, value));
    }

    /**
     * return the Transformer factory associated to this liaison.
     * @return the Transformer factory associated to this liaison.
     * @throws BuildException thrown if there is a problem creating
     * the factory.
     * @see #setFactory(String)
     * @since Ant 1.5.2
     */
    private TransformerFactory getFactory() throws BuildException {
        if (tfactory != null) {
            return tfactory;
        }
        // not initialized yet, so create the factory
        if (factoryName == null) {
            tfactory = TransformerFactory.newInstance();
        } else {
            try {
                Class<?> clazz = null;
                try {
                    clazz =
                        Class.forName(factoryName, true,
                                      Thread.currentThread()
                                      .getContextClassLoader());
                } catch (final ClassNotFoundException cnfe) {
                    final String msg = "Failed to load " + factoryName
                        + " via the configured classpath, will try"
                        + " Ant's classpath instead.";
                    if (logger != null) {
                        logger.log(msg);
                    } else if (project != null) {
                        project.log(msg, Project.MSG_WARN);
                    } else {
                        System.err.println(msg);
                    }
                }

                if (clazz == null) {
                    clazz = Class.forName(factoryName);
                }
                tfactory = (TransformerFactory) clazz.getDeclaredConstructor().newInstance();
            } catch (final Exception e) {
                throw new BuildException(e);
            }
        }

        applyReflectionHackForExtensionMethods();

        tfactory.setErrorListener(this);

        // specific attributes for the transformer
        for (final Object[] pair : attributes) {
            tfactory.setAttribute((String) pair[0], pair[1]);
        }

        for (Map.Entry<String, Boolean> feature : features.entrySet()) {
            try {
                tfactory.setFeature(feature.getKey(), feature.getValue());
            } catch (TransformerConfigurationException ex) {
                throw new BuildException(ex);
            }
        }

        if (uriResolver != null) {
            tfactory.setURIResolver(uriResolver);
        }
        return tfactory;
    }

    /**
     * Set the factory name to use instead of JAXP default lookup.
     * @param name the fully qualified class name of the factory to use
     * or null for the default JAXP look up mechanism.
     * @since Ant 1.6
     */
    public void setFactory(final String name) {
        factoryName = name;
    }

    /**
     * Set a custom attribute for the JAXP factory implementation.
     * @param name the attribute name.
     * @param value the value of the attribute, usually a boolean
     * string or object.
     * @since Ant 1.6
     */
    public void setAttribute(final String name, final Object value) {
        final Object[] pair = new Object[]{name, value};
        attributes.add(pair);
    }

    /**
     * Set a custom feature for the JAXP factory implementation.
     * @param name the feature name.
     * @param value the value of the feature
     * @since Ant 1.9.8
     */
    public void setFeature(final String name, final boolean value) {
        features.put(name, value);
    }

    /**
     * Set the output property for the current transformer.
     * Note that the stylesheet must be set prior to calling
     * this method.
     * @param name the output property name.
     * @param value the output property value.
     * @since Ant 1.5
     * @since Ant 1.5
     */
    public void setOutputProperty(final String name, final String value) {
        final String[] pair = new String[]{name, value};
        outputProperties.addElement(pair);
    }

    /**
     * Set the class to resolve entities during the transformation.
     * @param aResolver the resolver class.
     */
    public void setEntityResolver(final EntityResolver aResolver) {
        entityResolver = aResolver;
    }

    /**
     * Set the class to resolve URIs during the transformation
     * @param aResolver a <code>EntityResolver</code> value
     */
    public void setURIResolver(final URIResolver aResolver) {
        uriResolver = aResolver;
    }

    /**
     * Add a parameter.
     * @param name the name of the parameter
     * @param value the value of the parameter
     */
    public void addParam(final String name, final String value) {
        params.put(name, value);
    }

    /**
     * Add a parameter.
     * @param name the name of the parameter
     * @param value the value of the parameter
     * @since Ant 1.9.3
     */
    public void addParam(final String name, final Object value) {
        params.put(name, value);
    }

    /**
     * Set a logger.
     * @param l a logger.
     */
    public void setLogger(final XSLTLogger l) {
        logger = l;
    }

    /**
     * Log an error.
     * @param e the exception to log.
     */
    public void error(final TransformerException e) {
        logError(e, "Error");
    }

    /**
     * Log a fatal error.
     * @param e the exception to log.
     */
    public void fatalError(final TransformerException e) {
        logError(e, "Fatal Error");
        throw new BuildException("Fatal error during transformation using " + stylesheet + ": " + e.getMessageAndLocation(), e);
    }

    /**
     * Log a warning.
     * @param e the exception to log.
     */
    public void warning(final TransformerException e) {
        if (!suppressWarnings) {
            logError(e, "Warning");
        }
    }

    private void logError(final TransformerException e, final String type) {
        if (logger == null) {
            return;
        }

        final StringBuffer msg = new StringBuffer();
        final SourceLocator locator = e.getLocator();
        if (locator != null) {
            final String systemid = locator.getSystemId();
            if (systemid != null) {
                String url = systemid;
                if (url.startsWith("file:")) {
                    url = FileUtils.getFileUtils().fromURI(url);
                }
                msg.append(url);
            } else {
                msg.append("Unknown file");
            }
            final int line = locator.getLineNumber();
            if (line != -1) {
                msg.append(":");
                msg.append(line);
                final int column = locator.getColumnNumber();
                if (column != -1) {
                    msg.append(":");
                    msg.append(column);
                }
            }
        }
        msg.append(": ");
        msg.append(type);
        msg.append("! ");
        msg.append(e.getMessage());
        if (e.getCause() != null) {
            msg.append(" Cause: ");
            msg.append(e.getCause());
        }

        logger.log(msg.toString());
    }

    // kept for backwards compatibility
    /**
     * @param file the filename to use for the systemid
     * @return the systemid
     * @deprecated since 1.5.x.
     *             Use org.apache.tools.ant.util.JAXPUtils#getSystemId instead.
     */
    @Deprecated
    protected String getSystemId(final File file) {
        return JAXPUtils.getSystemId(file);
    }


    /**
     * Specific configuration for the TRaX liaison.
     * @param xsltTask the XSLTProcess task instance from which this liaison
     *        is to be configured.
     */
    public void configure(final XSLTProcess xsltTask) {
        project = xsltTask.getProject();
        final XSLTProcess.Factory factory = xsltTask.getFactory();
        if (factory != null) {
            setFactory(factory.getName());
            // configure factory attributes
            StreamUtils.enumerationAsStream(factory.getAttributes())
                    .forEach(attr -> setAttribute(attr.getName(), attr.getValue()));
            factory.getFeatures()
                    .forEach(feature -> setFeature(feature.getName(), feature.getValue()));
        }

        final XMLCatalog xmlCatalog = xsltTask.getXMLCatalog();
        // use XMLCatalog as the entity resolver and URI resolver
        if (xmlCatalog != null) {
            setEntityResolver(xmlCatalog);
            setURIResolver(xmlCatalog);
        }

        // configure output properties
        StreamUtils.enumerationAsStream(xsltTask.getOutputProperties())
                .forEach(prop -> setOutputProperty(prop.getName(), prop.getValue()));

        suppressWarnings = xsltTask.getSuppressWarnings();

        traceConfiguration = xsltTask.getTraceConfiguration();
    }

    private void applyReflectionHackForExtensionMethods() {
        // Jigsaw doesn't allow reflection to work, so we can stop trying
        if (!JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
            try { // #51668, #52382
                final Field _isNotSecureProcessing = tfactory.getClass().getDeclaredField("_isNotSecureProcessing");
                _isNotSecureProcessing.setAccessible(true);
                _isNotSecureProcessing.set(tfactory, Boolean.TRUE);
            } catch (final Exception x) {
                if (project != null) {
                    project.log(x.toString(), Project.MSG_DEBUG);
                }
            }
        }
    }

}
