/*
 * 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.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.jsp.tagext.FunctionInfo;

import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.tomcat.util.security.PrivilegedGetTccl;

/**
 * This class generates functions mappers for the EL expressions in the page.
 * Instead of a global mapper, a mapper is used for each call to EL
 * evaluator, thus avoiding the prefix overlapping and redefinition
 * issues.
 *
 * @author Kin-man Chung
 */

public class ELFunctionMapper {
    private int currFunc = 0;
    private StringBuilder ds;  // Contains codes to initialize the functions mappers.
    private StringBuilder ss;  // Contains declarations of the functions mappers.

    /**
     * Creates the functions mappers for all EL expressions in the JSP page.
     *
     * @param page The current compilation unit.
     */
    public static void map(Node.Nodes page)
                throws JasperException {

        ELFunctionMapper map = new ELFunctionMapper();
        map.ds = new StringBuilder();
        map.ss = new StringBuilder();

        page.visit(map.new ELFunctionVisitor());

        // Append the declarations to the root node
        String ds = map.ds.toString();
        if (ds.length() > 0) {
            Node root = page.getRoot();
            @SuppressWarnings("unused")
            Node unused = new Node.Declaration(map.ss.toString(), null, root);
            unused = new Node.Declaration(
                    "static {\n" + ds + "}\n", null, root);
        }
    }

    /**
     * A visitor for the page.  The places where EL is allowed are scanned
     * for functions, and if found functions mappers are created.
     */
    private class ELFunctionVisitor extends Node.Visitor {

        /**
         * Use a global name map to facilitate reuse of function maps.
         * The key used is prefix:function:uri.
         */
        private final HashMap<String, String> gMap = new HashMap<>();

        @Override
        public void visit(Node.ParamAction n) throws JasperException {
            doMap(n.getValue());
            visitBody(n);
        }

        @Override
        public void visit(Node.IncludeAction n) throws JasperException {
            doMap(n.getPage());
            visitBody(n);
        }

        @Override
        public void visit(Node.ForwardAction n) throws JasperException {
            doMap(n.getPage());
            visitBody(n);
        }

        @Override
        public void visit(Node.SetProperty n) throws JasperException {
            doMap(n.getValue());
            visitBody(n);
        }

        @Override
        public void visit(Node.UseBean n) throws JasperException {
            doMap(n.getBeanName());
            visitBody(n);
        }

        @Override
        public void visit(Node.PlugIn n) throws JasperException {
            doMap(n.getHeight());
            doMap(n.getWidth());
            visitBody(n);
        }

        @Override
        public void visit(Node.JspElement n) throws JasperException {

            Node.JspAttribute[] attrs = n.getJspAttributes();
            for (int i = 0; attrs != null && i < attrs.length; i++) {
                doMap(attrs[i]);
            }
            doMap(n.getNameAttribute());
            visitBody(n);
        }

        @Override
        public void visit(Node.UninterpretedTag n) throws JasperException {

            Node.JspAttribute[] attrs = n.getJspAttributes();
            for (int i = 0; attrs != null && i < attrs.length; i++) {
                doMap(attrs[i]);
            }
            visitBody(n);
        }

        @Override
        public void visit(Node.CustomTag n) throws JasperException {
            Node.JspAttribute[] attrs = n.getJspAttributes();
            for (int i = 0; attrs != null && i < attrs.length; i++) {
                doMap(attrs[i]);
            }
            visitBody(n);
        }

        @Override
        public void visit(Node.ELExpression n) throws JasperException {
            doMap(n.getEL());
        }

        private void doMap(Node.JspAttribute attr)
                throws JasperException {
            if (attr != null) {
                doMap(attr.getEL());
            }
        }

        /**
         * Creates function mappers, if needed, from ELNodes
         */
        private void doMap(ELNode.Nodes el)
                throws JasperException {

            // Only care about functions in ELNode's
            class Fvisitor extends ELNode.Visitor {
                private final List<ELNode.Function> funcs = new ArrayList<>();
                private final Set<String> keySet = new HashSet<>();
                @Override
                public void visit(ELNode.Function n) throws JasperException {
                    String key = n.getPrefix() + ":" + n.getName();
                    if (keySet.add(key)) {
                        funcs.add(n);
                    }
                }
            }

            if (el == null) {
                return;
            }

            // First locate all unique functions in this EL
            Fvisitor fv = new Fvisitor();
            el.visit(fv);
            List<ELNode.Function> functions = fv.funcs;

            if (functions.size() == 0) {
                return;
            }

            // Reuse a previous map if possible
            String decName = matchMap(functions);
            if (decName != null) {
                el.setMapName(decName);
                return;
            }

            // Generate declaration for the map statically
            decName = getMapName();
            ss.append("private static org.apache.jasper.runtime.ProtectedFunctionMapper " + decName + ";\n");

            ds.append("  " + decName + "= ");
            ds.append("org.apache.jasper.runtime.ProtectedFunctionMapper");

            // Special case if there is only one function in the map
            String funcMethod = null;
            if (functions.size() == 1) {
                funcMethod = ".getMapForFunction";
            } else {
                ds.append(".getInstance();\n");
                funcMethod = "  " + decName + ".mapFunction";
            }

            // Setup arguments for either getMapForFunction or mapFunction
            for (ELNode.Function f : functions) {
                FunctionInfo funcInfo = f.getFunctionInfo();
                String fnQName = f.getPrefix() + ":" + f.getName();
                if (funcInfo == null) {
                    // Added via Lambda or ImportHandler. EL will expect a
                    // function mapper even if one isn't used so just pass null
                    ds.append(funcMethod + "(null, null, null, null);\n");
                } else {
                    ds.append(funcMethod + "(\"" + fnQName + "\", " +
                            getCanonicalName(funcInfo.getFunctionClass()) +
                            ".class, " + '\"' + f.getMethodName() + "\", " +
                            "new Class[] {");
                    String params[] = f.getParameters();
                    for (int k = 0; k < params.length; k++) {
                        if (k != 0) {
                            ds.append(", ");
                        }
                        int iArray = params[k].indexOf('[');
                        if (iArray < 0) {
                            ds.append(params[k] + ".class");
                        }
                        else {
                            String baseType = params[k].substring(0, iArray);
                            ds.append("java.lang.reflect.Array.newInstance(");
                            ds.append(baseType);
                            ds.append(".class,");

                            // Count the number of array dimension
                            int aCount = 0;
                            for (int jj = iArray; jj < params[k].length(); jj++ ) {
                                if (params[k].charAt(jj) == '[') {
                                    aCount++;
                                }
                            }
                            if (aCount == 1) {
                                ds.append("0).getClass()");
                            } else {
                                ds.append("new int[" + aCount + "]).getClass()");
                            }
                        }
                    }
                    ds.append("});\n");
                }
                // Put the current name in the global function map
                gMap.put(fnQName + ':' + f.getUri(), decName);
            }
            el.setMapName(decName);
        }

        /**
         * Find the name of the function mapper for an EL.  Reuse a
         * previously generated one if possible.
         * @param functions A List of ELNode.Function instances that
         *                  represents the functions in an EL
         * @return A previous generated function mapper name that can be used
         *         by this EL; null if none found.
         */
        private String matchMap(List<ELNode.Function> functions) {

            String mapName = null;
            for (ELNode.Function f : functions) {
                String temName = gMap.get(f.getPrefix() + ':' + f.getName() +
                        ':' + f.getUri());
                if (temName == null) {
                    return null;
                }
                if (mapName == null) {
                    mapName = temName;
                } else if (!temName.equals(mapName)) {
                    // If not all in the previous match, then no match.
                    return null;
                }
            }
            return mapName;
        }

        /*
         * @return An unique name for a function mapper.
         */
        private String getMapName() {
            return "_jspx_fnmap_" + currFunc++;
        }

        /**
         * Convert a binary class name into a canonical one that can be used
         * when generating Java source code.
         *
         * @param className Binary class name
         * @return          Canonical equivalent
         */
        private String getCanonicalName(String className) throws JasperException {
            Class<?> clazz;

            ClassLoader tccl;
            if (Constants.IS_SECURITY_ENABLED) {
                PrivilegedAction<ClassLoader> pa = new PrivilegedGetTccl();
                tccl = AccessController.doPrivileged(pa);
            } else {
                tccl = Thread.currentThread().getContextClassLoader();
            }

            try {
                clazz = Class.forName(className, false, tccl);
            } catch (ClassNotFoundException e) {
                throw new JasperException(e);
            }
            return clazz.getCanonicalName();
        }
    }
}

