/*
 * 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.IOException;
import java.net.URL;
import java.security.AccessController;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;

import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.tagplugin.TagPlugin;
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
import org.apache.tomcat.util.descriptor.tagplugin.TagPluginParser;
import org.apache.tomcat.util.security.PrivilegedGetTccl;
import org.apache.tomcat.util.security.PrivilegedSetTccl;
import org.xml.sax.SAXException;

/**
 * Manages tag plugin optimizations.
 *
 * @author Kin-man Chung
 */
public class TagPluginManager {

    private static final String META_INF_JASPER_TAG_PLUGINS_XML =
            "META-INF/org.apache.jasper/tagPlugins.xml";
    private static final String TAG_PLUGINS_XML = "/WEB-INF/tagPlugins.xml";
    private final ServletContext ctxt;
    private HashMap<String, TagPlugin> tagPlugins;
    private boolean initialized = false;

    public TagPluginManager(ServletContext ctxt) {
        this.ctxt = ctxt;
    }

    public void apply(Node.Nodes page, ErrorDispatcher err, PageInfo pageInfo)
            throws JasperException {

        init(err);
        if (!tagPlugins.isEmpty()) {
            page.visit(new NodeVisitor(this, pageInfo));
        }
    }

    private void init(ErrorDispatcher err) throws JasperException {
        if (initialized)
            return;

        String blockExternalString = ctxt.getInitParameter(
                Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
        boolean blockExternal;
        if (blockExternalString == null) {
            blockExternal = true;
        } else {
            blockExternal = Boolean.parseBoolean(blockExternalString);
        }

        TagPluginParser parser;
        ClassLoader original;
        if (Constants.IS_SECURITY_ENABLED) {
            PrivilegedGetTccl pa = new PrivilegedGetTccl();
            original = AccessController.doPrivileged(pa);
        } else {
            original = Thread.currentThread().getContextClassLoader();
        }
        try {
            if (Constants.IS_SECURITY_ENABLED) {
                PrivilegedSetTccl pa =
                        new PrivilegedSetTccl(TagPluginManager.class.getClassLoader());
                AccessController.doPrivileged(pa);
            } else {
                Thread.currentThread().setContextClassLoader(
                        TagPluginManager.class.getClassLoader());
            }

            parser = new TagPluginParser(ctxt, blockExternal);

            Enumeration<URL> urls =
                    ctxt.getClassLoader().getResources(META_INF_JASPER_TAG_PLUGINS_XML);
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                parser.parse(url);
            }

            URL url = ctxt.getResource(TAG_PLUGINS_XML);
            if (url != null) {
                parser.parse(url);
            }
        } catch (IOException | SAXException e) {
            throw new JasperException(e);
        } finally {
            if (Constants.IS_SECURITY_ENABLED) {
                PrivilegedSetTccl pa = new PrivilegedSetTccl(original);
                AccessController.doPrivileged(pa);
            } else {
                Thread.currentThread().setContextClassLoader(original);
            }
        }

        Map<String, String> plugins = parser.getPlugins();
        tagPlugins = new HashMap<>(plugins.size());
        for (Map.Entry<String, String> entry : plugins.entrySet()) {
            try {
                String tagClass = entry.getKey();
                String pluginName = entry.getValue();
                Class<?> pluginClass = ctxt.getClassLoader().loadClass(pluginName);
                TagPlugin plugin = (TagPlugin) pluginClass.getConstructor().newInstance();
                tagPlugins.put(tagClass, plugin);
            } catch (Exception e) {
                err.jspError(e);
            }
        }
        initialized = true;
    }

    /**
     * Invoke tag plugin for the given custom tag, if a plugin exists for
     * the custom tag's tag handler.
     * <p/>
     * The given custom tag node will be manipulated by the plugin.
     */
    private void invokePlugin(Node.CustomTag n, PageInfo pageInfo) {
        TagPlugin tagPlugin = tagPlugins.get(n.getTagHandlerClass().getName());
        if (tagPlugin == null) {
            return;
        }

        TagPluginContext tagPluginContext = new TagPluginContextImpl(n, pageInfo);
        n.setTagPluginContext(tagPluginContext);
        tagPlugin.doTag(tagPluginContext);
    }

    private static class NodeVisitor extends Node.Visitor {
        private final TagPluginManager manager;
        private final PageInfo pageInfo;

        public NodeVisitor(TagPluginManager manager, PageInfo pageInfo) {
            this.manager = manager;
            this.pageInfo = pageInfo;
        }

        @Override
        public void visit(Node.CustomTag n) throws JasperException {
            manager.invokePlugin(n, pageInfo);
            visitBody(n);
        }
    }

    private static class TagPluginContextImpl implements TagPluginContext {
        private final Node.CustomTag node;
        private final PageInfo pageInfo;
        private final HashMap<String, Object> pluginAttributes;
        private Node.Nodes curNodes;

        TagPluginContextImpl(Node.CustomTag n, PageInfo pageInfo) {
            this.node = n;
            this.pageInfo = pageInfo;
            curNodes = new Node.Nodes();
            n.setAtETag(curNodes);
            curNodes = new Node.Nodes();
            n.setAtSTag(curNodes);
            n.setUseTagPlugin(true);
            pluginAttributes = new HashMap<>();
        }

        @Override
        public TagPluginContext getParentContext() {
            Node parent = node.getParent();
            if (!(parent instanceof Node.CustomTag)) {
                return null;
            }
            return ((Node.CustomTag) parent).getTagPluginContext();
        }

        @Override
        public void setPluginAttribute(String key, Object value) {
            pluginAttributes.put(key, value);
        }

        @Override
        public Object getPluginAttribute(String key) {
            return pluginAttributes.get(key);
        }

        @Override
        public boolean isScriptless() {
            return node.getChildInfo().isScriptless();
        }

        @Override
        public boolean isConstantAttribute(String attribute) {
            Node.JspAttribute attr = getNodeAttribute(attribute);
            if (attr == null)
                return false;
            return attr.isLiteral();
        }

        @Override
        public String getConstantAttribute(String attribute) {
            Node.JspAttribute attr = getNodeAttribute(attribute);
            if (attr == null)
                return null;
            return attr.getValue();
        }

        @Override
        public boolean isAttributeSpecified(String attribute) {
            return getNodeAttribute(attribute) != null;
        }

        @Override
        public String getTemporaryVariableName() {
            return node.getRoot().nextTemporaryVariableName();
        }

        @Override
        public void generateImport(String imp) {
            pageInfo.addImport(imp);
        }

        @Override
        public void generateDeclaration(String id, String text) {
            if (pageInfo.isPluginDeclared(id)) {
                return;
            }
            curNodes.add(new Node.Declaration(text, node.getStart(), null));
        }

        @Override
        public void generateJavaSource(String sourceCode) {
            curNodes.add(new Node.Scriptlet(sourceCode, node.getStart(),
                    null));
        }

        @Override
        public void generateAttribute(String attributeName) {
            curNodes.add(new Node.AttributeGenerator(node.getStart(),
                    attributeName,
                    node));
        }

        @Override
        public void dontUseTagPlugin() {
            node.setUseTagPlugin(false);
        }

        @Override
        public void generateBody() {
            // Since we'll generate the body anyway, this is really a nop,
            // except for the fact that it lets us put the Java sources the
            // plugins produce in the correct order (w.r.t the body).
            curNodes = node.getAtETag();
        }

        @Override
        public boolean isTagFile() {
            return pageInfo.isTagFile();
        }

        private Node.JspAttribute getNodeAttribute(String attribute) {
            Node.JspAttribute[] attrs = node.getJspAttributes();
            for (int i = 0; attrs != null && i < attrs.length; i++) {
                if (attrs[i].getName().equals(attribute)) {
                    return attrs[i];
                }
            }
            return null;
        }
    }

}

