/*
 * 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.myfaces.extensions.scripting.core.util;

import org.apache.myfaces.extensions.scripting.api.Configuration;
import org.apache.myfaces.extensions.scripting.api.ScriptingConst;
import org.apache.myfaces.extensions.scripting.api.ScriptingWeaver;
import org.apache.myfaces.extensions.scripting.core.CoreWeaver;
import org.apache.myfaces.extensions.scripting.core.util.stax.FilterClassDigester;
import org.apache.myfaces.extensions.scripting.loaders.groovy.GroovyScriptingWeaver;
import org.apache.myfaces.extensions.scripting.loaders.java.JavaScriptingWeaver;
import org.apache.myfaces.extensions.scripting.loaders.java.RecompiledClassLoader;
import org.apache.myfaces.extensions.scripting.monitor.ResourceMonitor;
import org.apache.myfaces.extensions.scripting.monitor.RefreshContext;
import org.apache.myfaces.extensions.scripting.api.extensionevents.ExtensionEventRegistry;
import org.apache.myfaces.extensions.scripting.servlet.ScriptingServletFilter;

import javax.servlet.ServletContext;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Central initializer class for our
 * WeavingContext which does some semantic checking of the web.xml
 * and initializes everything in proper order
 *
 * @author Werner Punz (latest modification by $Author$)
 * @version $Revision$ $Date$
 */

public class WeavingContextInitializer {

    static class StartupException extends Exception {
        StartupException(String message) {
            super(message);
        }
    }

    static final Logger _logger = Logger.getLogger(WeavingContextInitializer.class.getName());

    static final PrivilegedExceptionAction<RecompiledClassLoader> LOADER_ACTION = new PrivilegedExceptionAction<RecompiledClassLoader>() {
        public RecompiledClassLoader run() {
            return new RecompiledClassLoader(ClassUtils.getContextClassLoader(), ScriptingConst.ENGINE_TYPE_JSF_JAVA, ".java");
        }
    };
    private static final String GROOVY_NOT_FOUND = "[EXT-SCRIPTING] Groovy not found disabling Ext-Scripting Groovy support";
    private static final String GROOVY_OBJECT = "groovy.lang.GroovyObject";

    public static void initWeavingContext(ServletContext servletContext) {
        try {
            WeavingContext.setScriptingEnabled(true);
            validateWebXml(servletContext);
            initConfiguration(servletContext);
            initExtensionEventSystem(servletContext);
            validateSecurityConstraints();
            initWeavers(servletContext);
            validateSourcePaths();
            initRefreshContext(servletContext);

            initFileChangeDaemon(servletContext);
            initExternalContext(servletContext);
        } catch (StartupException ex) {
            _logger.severe("[EXT-SCRIPTING] " + ex.getMessage());
            WeavingContext.setScriptingEnabled(false);
        }

    }

    /**
     * validates the source paths which were determined by the
     * startup for failures
     */
    private static void validateSourcePaths() throws StartupException {

        Collection<String> dirs = WeavingContext.getConfiguration().getAllSourceDirs();
        for (String currentDir : dirs) {
            File probe = new File(currentDir);
            if (!probe.exists()) {
                throw new StartupException("The directory " + probe + " does not exist, disabling scripting support");
            }
        }
    }

    /**
     * asserts the security constraints
     * the only security which has to be allowed
     * is the creation of classloaders
     */
    private static void validateSecurityConstraints() throws StartupException {

        try {
            AccessController.doPrivileged(LOADER_ACTION);
        } catch (PrivilegedActionException e) {
            throw new StartupException("Class loader creation is prohibited by your security settings, I am going to disable Ext-Scripting");
        }
    }

    private static void initExternalContext(ServletContext servletContext) {

        WeavingContext.setExternalContext(servletContext);
    }

    private static void initFileChangeDaemon(ServletContext servletContext) {

        ResourceMonitor.startup(servletContext);
        WeavingContext.getRefreshContext().setDaemon(ResourceMonitor.getInstance());
    }

    private static void initExtensionEventSystem(ServletContext servletContext) {
        ExtensionEventRegistry registry = new ExtensionEventRegistry();
        servletContext.setAttribute(ScriptingConst.CTX_ATTR_EXTENSION_EVENT_SYSTEM, registry);
        WeavingContext.setExtensionEventRegistry(registry);
    }




    private static void initConfiguration(ServletContext servletContext) {

        final Configuration configuration = new Configuration();
        servletContext.setAttribute(ScriptingConst.CTX_ATTR_CONFIGURATION, configuration);
        WeavingContext.setConfiguration(configuration);
        //we now add the resource loader path here

        /*
         * we define a set of closures (inner classes) which make
         * our code more reusable we define a strategy
         * for each comma delimited set of values
         */
        Strategy addResourceDirStrategy = new Strategy() {
            public void apply(Object element) {
                configuration.addResourceDir((String) element);
            }
        };
        Strategy addAdditionalClassPathStrategy = new Strategy() {
            public void apply(Object element) {
                configuration.addAdditionalClassPath((String) element);
            }
        };
        Strategy addWhiteListPackageStrategy = new Strategy() {
            public void apply(Object element) {
                configuration.addWhitelistPackage((String) element);
            }
        };

        /**
         * We now apply the values into our own lists
         */
        applyEntries(servletContext.getInitParameter(ScriptingConst.INIT_PARAM_RESOURCE_PATH), addResourceDirStrategy);
        applyEntries(servletContext.getInitParameter(ScriptingConst.INIT_PARAM_SCRIPTING_ADDITIONAL_CLASSPATH), addAdditionalClassPathStrategy);
        applyEntries(servletContext.getInitParameter(ScriptingConst.INIT_PARAM_SCRIPTING_PACKAGE_WHITELIST), addWhiteListPackageStrategy);

        String initialCompile = servletContext.getInitParameter(ScriptingConst.INIT_PARAM_INITIAL_COMPILE);

        configuration.setInitialCompile((initialCompile == null) || initialCompile.trim().toLowerCase().equals("true"));

    }

    private static void applyEntries(String val, Strategy strategy) {
        if (!StringUtils.isBlank(val)) {
            String[] splitVal = val.split(ScriptingConst.CONTEXT_VALUE_DIVIDER);
            for (String singleVal : splitVal) {
                strategy.apply(singleVal);
            }
        }
    }

    private static void validateWebXml(ServletContext context) throws StartupException {
        try {
            URL webXml = context.getResource("/WEB-INF/web.xml");

            if (webXml != null) {
                if (!FilterClassDigester.findFilter(webXml, ScriptingServletFilter.class)) {
                    throw new StartupException(ScriptingConst.ERR_SERVLET_FILTER);
                }
            }

        } catch (IOException e) {
            throw new StartupException("Web.xml could not be parsed disabling scripting");
        }
    }

    /**
     * inits the weaver chain which depends on the scripting
     * language supported by the internal jars
     *
     * @param servletContext the standard servlet context
     */
    private static void initWeavers(ServletContext servletContext) throws StartupException {
        _logger.fine("[EXT-SCRIPTING] initializing the weaving contexts");

        List<ScriptingWeaver> weavers = new ArrayList<ScriptingWeaver>(2);

        initGroovyWeaver(servletContext, weavers);
        initJavaWeaver(servletContext, weavers);
        if (WeavingContext.isFilterEnabled() && weavers.size() == 0) {
            throw new StartupException("No scripting languages initialized disabling EXT-SCRIPTING");
        }

        WeavingContext.setWeaver(new CoreWeaver(weavers));
        servletContext.setAttribute(ScriptingConst.CTX_ATTR_SCRIPTING_WEAVER, WeavingContext.getWeaver());
    }

    /**
     * inits the standard java weaver
     * for weaving and recompiling java classes on the fly
     *
     * @param servletContext the standard servlet context
     * @param weavers        our list of weavers which should receive the resulting weaver
     */
    private static void initJavaWeaver(ServletContext servletContext, List<ScriptingWeaver> weavers) throws StartupException {
        ScriptingWeaver javaWeaver = new JavaScriptingWeaver(servletContext);
        setupScriptingPaths(servletContext, javaWeaver, ScriptingConst.JAVA_SOURCE_ROOT, ScriptingConst.INIT_PARAM_CUSTOM_JAVA_LOADER_PATHS);
        if (WeavingContext.getConfiguration().getSourceDirs(ScriptingConst.ENGINE_TYPE_JSF_JAVA).size() > 0) {
            weavers.add(javaWeaver);
        } else {
            _logger.log(Level.WARNING, "[EXT-SCRIPTING] No valid source path for Java found either add WEB-INF/java to your filesystem, or add a custom Java source path, disabling EXT-SCRIPTING Java support");
        }
    }

    /**
     * initializes our groovy weaver
     *
     * @param servletContext the servlet context
     * @param weavers        the list of weavers receiving the resulting weaver if an initialization is possoble
     */
    private static void initGroovyWeaver(ServletContext servletContext, List<ScriptingWeaver> weavers) {
        //check if groovy can be enabled:
        try {
            Class groovyObject = ClassUtils.forName(GROOVY_OBJECT);
            if (groovyObject != null) {
                //groovy found ewe now enabled our groovy weaving support
                ScriptingWeaver groovyWeaver = new GroovyScriptingWeaver(servletContext);
                setupScriptingPaths(servletContext, groovyWeaver, ScriptingConst.GROOVY_SOURCE_ROOT, ScriptingConst.INIT_PARAM_CUSTOM_GROOVY_LOADER_PATHS);
                if (WeavingContext.getConfiguration().getSourceDirs(ScriptingConst.ENGINE_TYPE_JSF_GROOVY).size() > 0) {
                    weavers.add(groovyWeaver);
                } else {
                    _logger.log(Level.WARNING, "[EXT-SCRIPTING] No valid source path for Groovy found either add WEB-INF/groovy to your filesystem, or add a custom Groovy source path, disabling EXT-SCRIPTING Groovy support");
                }
            }

        } catch (Exception e) {
            _logger.info(GROOVY_NOT_FOUND);
        }
    }

    /**
     * initialisation of the refresh context object
     * the refresh context, is a context object which keeps
     * the refresh information (refresh time, needs refresh) etc...
     *
     * @param servletContext the servlet context singleton which keeps
     *                       the context for distribution
     */
    private static void initRefreshContext(ServletContext servletContext) {
        _logger.fine("[EXT-SCRIPTING] initializing the refresh context");

        RefreshContext rContext = new RefreshContext();
        servletContext.setAttribute(ScriptingConst.CTX_ATTR_REFRESH_CONTEXT, rContext);
        WeavingContext.setRefreshContext(rContext);
    }

    private static void setupScriptingPaths(ServletContext servletContext, ScriptingWeaver weaver, String contextRootKey, String initParams) throws StartupException {

        String classRoot = "";
        String scriptingRoot;

        String additionalLoaderPaths;

        String contextRoot = servletContext.getRealPath(contextRootKey);

        if (contextRoot == null) {
            _logger.warning("[EXT-SCRIPTING] one of the standard paths could not be resolved: " + contextRootKey + " this is either due to the path is missing or due to a configuration error! You can bypass the problem by setting additional loader paths if they are not set already!");
            contextRoot = "";

        }

        contextRoot = contextRoot.trim();
        scriptingRoot = contextRoot;

        additionalLoaderPaths = servletContext.getInitParameter(initParams);
        appendAdditionalPaths(additionalLoaderPaths, weaver);
        if (additionalLoaderPaths == null || additionalLoaderPaths.trim().equals("")) {
            if (contextRoot.equals("")) {
                throw new StartupException("Standard paths (WEB-INF/groovy and WEB-INF/java could not be determined, also no additional loader paths are set, I cannot start properly, please set additional loader paths for Ext-Scripting to work correctly! I am disabling Ext-Scripting!");
            }
            if (!StringUtils.isBlank(scriptingRoot)) {
                File probe = new File(scriptingRoot);
                if (probe.exists()) {
                    weaver.appendCustomScriptPath(scriptingRoot);

                } else {
                    _logger.log(Level.WARNING, "[EXT-SCRIPING] path {0} could not be found this might cause compile problems ", scriptingRoot);
                }
            }
            if (!StringUtils.isBlank(classRoot)) {
                weaver.appendCustomScriptPath(classRoot);
            }
        }

    }

    private static void appendAdditionalPaths(String additionalLoaderPaths, ScriptingWeaver workWeaver) {
        if (!StringUtils.isBlank(additionalLoaderPaths)) {
            String[] additionalPaths = additionalLoaderPaths.split(",");
            for (String path : additionalPaths) {
                workWeaver.appendCustomScriptPath(path);
            }
        }
    }

}
