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

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
import org.apache.jasper.Options;
import org.apache.jasper.TrimSpacesOption;
import org.apache.jasper.servlet.JspServletWrapper;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.Jar;
import org.apache.tomcat.util.buf.CloseableURLConnection;
import org.apache.tomcat.util.descriptor.tld.TldResourcePath;
import org.apache.tomcat.util.scan.JarFactory;

/**
 * Main JSP compiler class. This class uses Ant for compiling.
 */
public abstract class Compiler {

    /**
     * Default constructor for Compiler.
     */
    public Compiler() {
    }

    private final Log log = LogFactory.getLog(Compiler.class); // must not be static

    // ----------------------------------------------------- Instance Variables

    /**
     * The JSP compilation context.
     */
    protected JspCompilationContext ctxt;

    /**
     * The error dispatcher.
     */
    protected ErrorDispatcher errDispatcher;

    /**
     * The page information.
     */
    protected PageInfo pageInfo;

    /**
     * The JSP servlet wrapper.
     */
    protected JspServletWrapper jsw;

    /**
     * The tag file processor.
     */
    protected TagFileProcessor tfp;

    /**
     * The compilation options.
     */
    protected Options options;

    /**
     * The page nodes.
     */
    protected Node.Nodes pageNodes;


    // ------------------------------------------------------------ Constructor

    /**
     * Initializes the compiler with the given compilation context and servlet wrapper.
     *
     * @param ctxt the JSP compilation context
     * @param jsw the JSP servlet wrapper
     */
    public void init(JspCompilationContext ctxt, JspServletWrapper jsw) {
        this.jsw = jsw;
        this.ctxt = ctxt;
        this.options = ctxt.getOptions();
    }


    // --------------------------------------------------------- Public Methods

    /**
     * Returns the source map for the specified class.
     *
     * @param className the class name
     *
     * @return the source map, or {@code null} if not available
     */
    public SmapStratum getSmap(String className) {

        Map<String,SmapStratum> smaps = ctxt.getRuntimeContext().getSmaps();
        SmapStratum smap = smaps.get(className);

        if (smap == null && !options.isSmapSuppressed()) {
            // Tomcat was restarted so cached SMAP has been lost. However, it
            // was written to the class file so it can be recovered.
            smap = SmapUtil.loadSmap(className, ctxt.getJspLoader());
            if (smap != null) {
                smaps.put(className, smap);
            }
        }

        return smap;
    }


    /**
     * Compile the jsp file into equivalent servlet in .java file
     *
     * @return A map of class names to JSR 045 source maps
     *
     * @throws Exception Error generating Java source
     */
    protected Map<String,SmapStratum> generateJava() throws Exception {

        long t1 = 0;
        long t2 = 0;
        long t3 = 0;
        long t4;

        if (log.isDebugEnabled()) {
            t1 = System.currentTimeMillis();
        }

        // Setup page info area
        pageInfo = new PageInfo(new BeanRepository(ctxt.getClassLoader(), errDispatcher), ctxt);

        JspConfig jspConfig = options.getJspConfig();
        JspConfig.JspProperty jspProperty = jspConfig.findJspProperty(ctxt.getJspFile());

        /*
         * If the current uri is matched by a pattern specified in a jsp-property-group in web.xml, initialize pageInfo
         * with those properties.
         */
        if (jspProperty.isELIgnored() != null) {
            pageInfo.setELIgnored(JspUtil.booleanValue(jspProperty.isELIgnored()));
        }
        if (jspProperty.getErrorOnELNotFound() != null) {
            pageInfo.setErrorOnELNotFound(JspUtil.booleanValue(jspProperty.getErrorOnELNotFound()));
        }
        if (jspProperty.isScriptingInvalid() != null) {
            pageInfo.setScriptingInvalid(JspUtil.booleanValue(jspProperty.isScriptingInvalid()));
        }
        if (jspProperty.getIncludePrelude() != null) {
            pageInfo.setIncludePrelude(jspProperty.getIncludePrelude());
        }
        if (jspProperty.getIncludeCoda() != null) {
            pageInfo.setIncludeCoda(jspProperty.getIncludeCoda());
        }
        if (jspProperty.isDeferedSyntaxAllowedAsLiteral() != null) {
            pageInfo.setDeferredSyntaxAllowedAsLiteral(
                    JspUtil.booleanValue(jspProperty.isDeferedSyntaxAllowedAsLiteral()));
        }
        if (jspProperty.isTrimDirectiveWhitespaces() != null) {
            pageInfo.setTrimDirectiveWhitespaces(JspUtil.booleanValue(jspProperty.isTrimDirectiveWhitespaces()));
        }
        // Default ContentType processing is deferred until after the page has
        // been parsed
        if (jspProperty.getBuffer() != null) {
            pageInfo.setBufferValue(jspProperty.getBuffer(), null, errDispatcher);
        }
        if (jspProperty.isErrorOnUndeclaredNamespace() != null) {
            pageInfo.setErrorOnUndeclaredNamespace(JspUtil.booleanValue(jspProperty.isErrorOnUndeclaredNamespace()));
        }
        if (ctxt.isTagFile()) {
            try {
                double libraryVersion = Double.parseDouble(ctxt.getTagInfo().getTagLibrary().getRequiredVersion());
                if (libraryVersion < 2.0) {
                    pageInfo.setIsELIgnored("true", null, errDispatcher, true);
                }
                if (libraryVersion < 2.1) {
                    pageInfo.setDeferredSyntaxAllowedAsLiteral("true", null, errDispatcher, true);
                }
            } catch (NumberFormatException ex) {
                errDispatcher.jspError(ex);
            }
        }

        ctxt.checkOutputDir();
        String javaFileName = ctxt.getServletJavaFileName();

        try {
            /*
             * The setting of isELIgnored changes the behaviour of the parser in subtle ways. To add to the 'fun',
             * isELIgnored can be set in any file that forms part of the translation unit so setting it in a file
             * included towards the end of the translation unit can change how the parser should have behaved when
             * parsing content up to the point where isELIgnored was set. Arghh! Previous attempts to hack around this
             * have only provided partial solutions. We now use two passes to parse the translation unit. The first just
             * parses the directives and the second parses the whole translation unit once we know how isELIgnored has
             * been set. TODO There are some possible optimisations of this process.
             */
            // Parse the file
            ParserController parserCtl = new ParserController(ctxt, this);

            // Pass 1 - the directives
            Node.Nodes directives = parserCtl.parseDirectives(ctxt.getJspFile());
            Validator.validateDirectives(this, directives);

            // Pass 2 - the whole translation unit
            pageNodes = parserCtl.parse(ctxt.getJspFile());

            // Leave this until now since it can only be set once - bug 49726
            if (pageInfo.getContentType() == null && jspProperty.getDefaultContentType() != null) {
                pageInfo.setContentType(jspProperty.getDefaultContentType());
            }

            if (ctxt.isPrototypeMode()) {
                // generate prototype .java file for the tag file
                try (ServletWriter writer = setupContextWriter(javaFileName)) {
                    Generator.generate(writer, this, pageNodes);
                    return null;
                }
            }

            // Validate and process attributes - don't re-validate the
            // directives we validated in pass 1
            Validator.validateExDirectives(this, pageNodes);

            if (log.isDebugEnabled()) {
                t2 = System.currentTimeMillis();
            }

            // Collect page info
            Collector.collect(this, pageNodes);

            // Compile (if necessary) and load the tag files referenced in
            // this compilation unit.
            tfp = new TagFileProcessor();
            tfp.loadTagFiles(this, pageNodes);

            if (log.isDebugEnabled()) {
                t3 = System.currentTimeMillis();
            }

            // Determine which custom tag needs to declare which scripting vars
            ScriptingVariabler.set(pageNodes, errDispatcher);

            // Optimizations by Tag Plugins
            TagPluginManager tagPluginManager = options.getTagPluginManager();
            tagPluginManager.apply(pageNodes, errDispatcher, pageInfo);

            // Optimization: concatenate contiguous template texts.
            TextOptimizer.concatenate(this, pageNodes);

            // Generate static function mapper codes.
            ELFunctionMapper.map(pageNodes);

            // generate servlet .java file
            try (ServletWriter writer = setupContextWriter(javaFileName)) {
                Generator.generate(writer, this, pageNodes);
            }

            // The writer is only used during compile, dereference
            // it in the JspCompilationContext when done to allow it
            // to be GCed and save memory.
            ctxt.setWriter(null);

            if (log.isTraceEnabled()) {
                t4 = System.currentTimeMillis();
                log.trace("Generated " + javaFileName + " total=" + (t4 - t1) + " generate=" + (t4 - t3) +
                        " validate=" + (t2 - t1));
            }

        } catch (RuntimeException e) {
            // Remove the generated .java file
            File file = new File(javaFileName);
            if (file.exists()) {
                if (!file.delete()) {
                    log.warn(Localizer.getMessage("jsp.warning.compiler.javafile.delete.fail", file.getAbsolutePath()));
                }
            }
            throw e;
        }

        Map<String,SmapStratum> smaps = null;

        // JSR45 Support
        if (!options.isSmapSuppressed()) {
            smaps = SmapUtil.generateSmap(ctxt, pageNodes);
            // Add them to the web application wide cache for future lookup in
            // error handling etc.
            ctxt.getRuntimeContext().getSmaps().putAll(smaps);
        }

        // If any prototype .java and .class files was generated,
        // the prototype .java may have been replaced by the current
        // compilation (if the tag file is self referencing), but the
        // .class file need to be removed, to make sure that javac would
        // generate .class again from the new .java file just generated.
        tfp.removeProtoTypeFiles(ctxt.getClassFileName());

        return smaps;
    }

    private ServletWriter setupContextWriter(String javaFileName) throws FileNotFoundException, JasperException {
        ServletWriter writer;
        // Set up the ServletWriter
        String javaEncoding = ctxt.getOptions().getJavaEncoding();
        OutputStreamWriter osw = null;

        try {
            osw = new OutputStreamWriter(new FileOutputStream(javaFileName), javaEncoding);
        } catch (UnsupportedEncodingException ex) {
            errDispatcher.jspError("jsp.error.needAlternateJavaEncoding", javaEncoding);
        }

        if (ctxt.getOptions().getTrimSpaces().equals(TrimSpacesOption.EXTENDED)) {
            writer = new NewlineReductionServletWriter(new PrintWriter(osw));
        } else {
            writer = new ServletWriter(new PrintWriter(osw));
        }

        ctxt.setWriter(writer);
        return writer;
    }

    /**
     * Servlet compilation. This compiles the generated sources into Servlets.
     *
     * @param smaps The source maps for the class(es) generated from the source file
     *
     * @throws FileNotFoundException Source files not found
     * @throws JasperException       Compilation error
     * @throws Exception             Some other error
     */
    protected abstract void generateClass(Map<String,SmapStratum> smaps)
            throws FileNotFoundException, JasperException, Exception;

    /**
     * Compile the jsp file from the current engine context.
     *
     * @throws FileNotFoundException Source files not found
     * @throws JasperException       Compilation error
     * @throws Exception             Some other error
     */
    public void compile() throws FileNotFoundException, JasperException, Exception {
        compile(true);
    }

    /**
     * Compile the jsp file from the current engine context. As a side effect, tag files that are referenced by this
     * page are also compiled.
     *
     * @param compileClass If true, generate both .java and .class file If false, generate only .java file
     *
     * @throws FileNotFoundException Source files not found
     * @throws JasperException       Compilation error
     * @throws Exception             Some other error
     */
    public void compile(boolean compileClass) throws FileNotFoundException, JasperException, Exception {
        compile(compileClass, false);
    }

    /**
     * Compile the jsp file from the current engine context. As a side effect, tag files that are referenced by this
     * page are also compiled.
     *
     * @param compileClass If true, generate both .java and .class file If false, generate only .java file
     * @param jspcMode     true if invoked from JspC, false otherwise
     *
     * @throws FileNotFoundException Source files not found
     * @throws JasperException       Compilation error
     * @throws Exception             Some other error
     */
    public void compile(boolean compileClass, boolean jspcMode)
            throws FileNotFoundException, JasperException, Exception {
        if (errDispatcher == null) {
            this.errDispatcher = new ErrorDispatcher(jspcMode);
        }

        try {
            final Long jspLastModified = ctxt.getLastModified(ctxt.getJspFile());
            Map<String,SmapStratum> smaps = generateJava();
            File javaFile = new File(ctxt.getServletJavaFileName());
            if (!javaFile.setLastModified(jspLastModified.longValue())) {
                throw new JasperException(Localizer.getMessage("jsp.error.setLastModified", javaFile));
            }
            if (compileClass) {
                generateClass(smaps);
                // Fix for bugzilla 41606
                // Set JspServletWrapper.servletClassLastModifiedTime after successful compile
                File targetFile = new File(ctxt.getClassFileName());
                if (targetFile.exists()) {
                    if (!targetFile.setLastModified(jspLastModified.longValue())) {
                        throw new JasperException(Localizer.getMessage("jsp.error.setLastModified", targetFile));
                    }
                    if (jsw != null) {
                        jsw.setServletClassLastModifiedTime(jspLastModified.longValue());
                    }
                }
            }
        } finally {
            if (tfp != null && ctxt.isPrototypeMode()) {
                tfp.removeProtoTypeFiles(null);
            }
            // Make sure these object which are only used during the
            // generation and compilation of the JSP page get
            // dereferenced so that they can be GCed and reduce the
            // memory footprint.
            tfp = null;
            errDispatcher = null;
            pageInfo = null;
            pageNodes = null;

            if (ctxt.getWriter() != null) {
                ctxt.getWriter().close();
                ctxt.setWriter(null);
            }
        }
    }

    /**
     * This is a protected method intended to be overridden by subclasses of Compiler. This is used by the compile
     * method to do all the compilation.
     *
     * @return <code>true</code> if the source generation and compilation should occur
     */
    public boolean isOutDated() {
        return isOutDated(true);
    }

    /**
     * Determine if a compilation is necessary by checking the time stamp of the JSP page with that of the corresponding
     * .class or .java file. If the page has dependencies, the check is also extended to its dependents, and so on. This
     * method can be overridden by a subclasses of Compiler.
     *
     * @param checkClass If true, check against .class file, if false, check against .java file.
     *
     * @return <code>true</code> if the source generation and compilation should occur
     */
    public boolean isOutDated(boolean checkClass) {

        if (jsw != null && (ctxt.getOptions().getModificationTestInterval() > 0)) {

            if (jsw.getLastModificationTest() + (ctxt.getOptions().getModificationTestInterval() * 1000L) > System
                    .currentTimeMillis()) {
                return false;
            }
            jsw.setLastModificationTest(System.currentTimeMillis());
        }

        // Test the target file first. Unless there is an error checking the
        // last modified time of the source (unlikely) the target is going to
        // have to be checked anyway. If the target doesn't exist (likely during
        // startup) this saves an unnecessary check of the source.
        File targetFile;
        if (checkClass) {
            targetFile = new File(ctxt.getClassFileName());
        } else {
            targetFile = new File(ctxt.getServletJavaFileName());
        }
        if (!targetFile.exists()) {
            return true;
        }
        long targetLastModified = targetFile.lastModified();
        if (checkClass && jsw != null) {
            jsw.setServletClassLastModifiedTime(targetLastModified);
        }

        Long jspRealLastModified = ctxt.getLastModified(ctxt.getJspFile());
        if (jspRealLastModified.longValue() < 0) {
            // Something went wrong - assume modification
            return true;
        }

        if (targetLastModified != jspRealLastModified.longValue()) {
            if (log.isTraceEnabled()) {
                log.trace("Compiler: outdated: " + targetFile + " " + targetLastModified);
            }
            return true;
        }

        // determine if source dependent files (e.g. includes using include
        // directives) have been changed.
        if (jsw == null) {
            return false;
        }

        Map<String,Long> depends = jsw.getDependants();
        if (depends == null) {
            return false;
        }

        for (Entry<String,Long> include : depends.entrySet()) {
            try {
                String key = include.getKey();
                URL includeUrl;
                long includeLastModified;
                if (key.startsWith("uri:")) {
                    // Key is a stable taglib URI used for TLDs in JARs outside
                    // the web application (avoids baking absolute paths into the
                    // generated code). Two forms exist:
                    //   "uri:<taglib-uri>"           – the JAR file itself
                    //   "uri:<taglib-uri>!/<entry>"  – a TLD entry within the JAR
                    int bangSlash = key.indexOf("!/");
                    String tagUri = bangSlash < 0
                            ? key.substring(4)
                            : key.substring(4, bangSlash);
                    TldCache tldCache = ctxt.getOptions().getTldCache();
                    TldResourcePath tldPath = tldCache.getTldResourcePath(tagUri);
                    if (tldPath == null) {
                        return true;
                    }
                    try (Jar jar = tldPath.openJar()) {
                        if (jar == null) {
                            return true;
                        }
                        if (bangSlash < 0) {
                            // JAR-level key: check the JAR file's last-modified
                            includeLastModified = jar.getLastModified();
                        } else {
                            // TLD-entry key: check the entry's last-modified within the JAR
                            String entryName = key.substring(bangSlash + 2);
                            includeLastModified = jar.getLastModified(entryName);
                        }
                    }
                } else if (key.startsWith("jar:jar:")) {
                    // Assume we constructed this correctly
                    int entryStart = key.lastIndexOf("!/");
                    String entry = key.substring(entryStart + 2);
                    try (Jar jar = JarFactory.newInstance(new URI(key.substring(4, entryStart)).toURL())) {
                        includeLastModified = jar.getLastModified(entry);
                    }
                } else {
                    if (key.startsWith("jar:") || key.startsWith("file:")) {
                        includeUrl = new URI(key).toURL();
                    } else {
                        includeUrl = ctxt.getResource(include.getKey());
                    }
                    if (includeUrl == null) {
                        return true;
                    }
                    try (CloseableURLConnection iuc = new CloseableURLConnection(includeUrl)) {
                        if (iuc.getConnection() instanceof JarURLConnection) {
                            includeLastModified = ((JarURLConnection) iuc.getConnection()).getJarEntry().getTime();
                        } else {
                            includeLastModified = iuc.getLastModified();
                        }
                    }
                }

                if (includeLastModified != include.getValue().longValue()) {
                    return true;
                }
            } catch (Exception e) {
                if (log.isDebugEnabled()) {
                    log.debug(Localizer.getMessage("jsp.error.compiler.missingResource"), e);
                }
                return true;
            }
        }

        return false;

    }

    /**
     * Returns the error dispatcher.
     *
     * @return the error dispatcher.
     */
    public ErrorDispatcher getErrorDispatcher() {
        return errDispatcher;
    }

    /**
     * Returns the page information.
     *
     * @return the info about the page under compilation
     */
    public PageInfo getPageInfo() {
        return pageInfo;
    }

    /**
     * Returns the JSP compilation context.
     *
     * @return the compilation context
     */
    public JspCompilationContext getCompilationContext() {
        return ctxt;
    }

    /**
     * Remove generated files
     */
    public void removeGeneratedFiles() {
        removeGeneratedClassFiles();

        try {
            File javaFile = new File(ctxt.getServletJavaFileName());
            if (log.isTraceEnabled()) {
                log.trace("Deleting " + javaFile);
            }
            if (javaFile.exists()) {
                if (!javaFile.delete()) {
                    log.warn(Localizer.getMessage("jsp.warning.compiler.javafile.delete.fail",
                            javaFile.getAbsolutePath()));
                }
            }
        } catch (Exception e) {
            // Remove as much as possible, log possible exceptions
            log.warn(Localizer.getMessage("jsp.warning.compiler.classfile.delete.fail.unknown"), e);
        }
    }

    /**
     * Remove generated class files.
     */
    public void removeGeneratedClassFiles() {
        try {
            File classFile = new File(ctxt.getClassFileName());
            if (log.isTraceEnabled()) {
                log.trace("Deleting " + classFile);
            }
            if (classFile.exists()) {
                if (!classFile.delete()) {
                    log.warn(Localizer.getMessage("jsp.warning.compiler.classfile.delete.fail",
                            classFile.getAbsolutePath()));
                }
            }
        } catch (Exception e) {
            // Remove as much as possible, log possible exceptions
            log.warn(Localizer.getMessage("jsp.warning.compiler.classfile.delete.fail.unknown"), e);
        }
    }
}
