/*******************************************************************************
 * 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.ofbiz.catalina.container;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.stream.Collectors;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Globals;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Valve;
import org.apache.catalina.authenticator.SingleSignOn;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.filters.RequestDumperFilter;
import org.apache.catalina.ha.ClusterManager;
import org.apache.catalina.ha.tcp.ReplicationValve;
import org.apache.catalina.ha.tcp.SimpleTcpCluster;
import org.apache.catalina.startup.ContextConfig;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.tribes.group.GroupChannel;
import org.apache.catalina.tribes.membership.McastService;
import org.apache.catalina.tribes.transport.MultiPointSender;
import org.apache.catalina.tribes.transport.ReplicationTransmitter;
import org.apache.catalina.tribes.transport.nio.NioReceiver;
import org.apache.catalina.util.ServerInfo;
import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.webresources.StandardRoot;
import org.apache.ofbiz.base.component.ComponentConfig;
import org.apache.ofbiz.base.concurrent.ExecutionPool;
import org.apache.ofbiz.base.container.Container;
import org.apache.ofbiz.base.container.ContainerConfig;
import org.apache.ofbiz.base.container.ContainerConfig.Configuration;
import org.apache.ofbiz.base.container.ContainerConfig.Configuration.Property;
import org.apache.ofbiz.base.container.ContainerException;
import org.apache.ofbiz.base.start.Start;
import org.apache.ofbiz.base.start.StartupCommand;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.util.EntityUtilProperties;
import org.apache.ofbiz.webapp.WebAppUtil;
import org.apache.tomcat.JarScanner;
import org.apache.tomcat.util.IntrospectionUtils;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.xml.sax.SAXException;

/**
 * CatalinaContainer -  Tomcat
 *
 * For more information about the AccessLogValve pattern visit the
 * <a href="https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Access_Log_Valve">Documentation</a>
 */
public class CatalinaContainer implements Container {

    public static final String module = CatalinaContainer.class.getName();

    private String name;
    private Tomcat tomcat;

    @Override
    public void init(List<StartupCommand> ofbizCommands, String name, String configFile) throws ContainerException {

        this.name = name;
        ContainerConfig.Configuration configuration = ContainerConfig.getConfiguration(name, configFile);
        Property engineConfig = retrieveTomcatEngineConfig(configuration);

        // tomcat setup
        tomcat = prepareTomcatServer(configuration, engineConfig);
        Engine engine = prepareTomcatEngine(tomcat, engineConfig);
        Host host = prepareHost(tomcat, null);

        // add realm and valve for Tomcat SSO
        if (EntityUtilProperties.propertyValueEquals("security", "security.login.tomcat.sso", "true")){
            boolean useEncryption = EntityUtilProperties.propertyValueEquals("security", "password.encrypt", "true");
            OFBizRealm ofBizRealm = new OFBizRealm();
            if (useEncryption){
                ofBizRealm.setCredentialHandler(new HashedCredentialHandler());
            } else {
                ofBizRealm.setCredentialHandler(new SimpleCredentialHandler());
            }
            host.setRealm(ofBizRealm);
            ((StandardHost)host).addValve(new SingleSignOn());
        }

        // clustering, valves and connectors setup
        Property clusterProps = prepareTomcatClustering(host, engineConfig);
        prepareTomcatEngineValves(engineConfig).forEach(valve -> ((StandardEngine)engine).addValve(valve));
        prepareTomcatConnectors(configuration).forEach(connector -> tomcat.getService().addConnector(connector));

        loadWebapps(tomcat, configuration, clusterProps);
    }

    public boolean start() throws ContainerException {
        try {
            tomcat.start();
        } catch (LifecycleException e) {
            throw new ContainerException(e);
        }

        for (Connector con: tomcat.getService().findConnectors()) {
            Debug.logInfo("Connector " + con.getProtocol() + " @ " + con.getPort() + " - " +
                (con.getSecure() ? "secure" : "not-secure") + " [" + con.getProtocolHandlerClassName() + "] started.", module);
        }
        Debug.logInfo("Started " + ServerInfo.getServerInfo(), module);
        return true;
    }

    public void stop() throws ContainerException {
        try {
            tomcat.stop();
        } catch (LifecycleException e) {
            /* Don't re-throw this exception or it will kill the rest of the shutdown process.
             * Happens usually when running tests. Output disabled unless in verbose */
            Debug.logVerbose(e, module);
        }
    }

    public String getName() {
        return name;
    }

    private Property retrieveTomcatEngineConfig(ContainerConfig.Configuration cc) throws ContainerException {
        List<ContainerConfig.Configuration.Property> engineProps = cc.getPropertiesWithValue("engine");
        if (UtilValidate.isEmpty(engineProps)) {
            throw new ContainerException("Cannot load CatalinaContainer; no engines defined.");
        }
        if (engineProps.size() > 1) {
            throw new ContainerException("Cannot load CatalinaContainer; more than one engine configuration found; only one is supported.");
        }
        return engineProps.get(0);
    }

    private Tomcat prepareTomcatServer(ContainerConfig.Configuration cc,
            ContainerConfig.Configuration.Property engineConfig) throws ContainerException {

        System.setProperty(Globals.CATALINA_HOME_PROP, System.getProperty("ofbiz.home") + "/" +
                    ContainerConfig.getPropertyValue(cc, "catalina-runtime-home", "runtime/catalina"));
        System.setProperty(Globals.CATALINA_BASE_PROP, System.getProperty(Globals.CATALINA_HOME_PROP));

        Tomcat tomcat = new Tomcat();
        tomcat.setBaseDir(System.getProperty("ofbiz.home"));

        Property defaultHostProp = engineConfig.getProperty("default-host");
        if (defaultHostProp == null) {
            throw new ContainerException("default-host element of server property is required for catalina!");
        }
        tomcat.setHostname(defaultHostProp.value);

        if (ContainerConfig.getPropertyValue(cc, "use-naming", false)) {
            tomcat.enableNaming();
        }

        StandardServer server = (StandardServer) tomcat.getServer();
        try {
            server.setGlobalNamingContext(new InitialContext());
        } catch (NamingException e) {
            throw new ContainerException(e);
        }

        return tomcat;
    }

    private Engine prepareTomcatEngine(Tomcat tomcat, Property engineConfig) {
        Engine engine = tomcat.getEngine();
        engine.setName(engineConfig.name);

        // set the JVM Route property (JK/JK2)
        String jvmRoute = ContainerConfig.getPropertyValue(engineConfig, "jvm-route", null);
        if (jvmRoute != null) {
            engine.setJvmRoute(jvmRoute);
        }

        return engine;
    }

    private Host prepareHost(Tomcat tomcat, List<String> virtualHosts) {
        Host host;

        if (UtilValidate.isEmpty(virtualHosts)) {
            host = (Host) tomcat.getEngine().findChild(tomcat.getEngine().getDefaultHost());
            if(host == null) {
                host = tomcat.getHost();
            }
        } else {
            host = prepareVirtualHost(tomcat, virtualHosts);
        }

        host.setAppBase(System.getProperty("ofbiz.home") + "/framework/catalina/hosts");
        host.setDeployOnStartup(false);
        host.setBackgroundProcessorDelay(5);
        host.setAutoDeploy(false);
        ((StandardHost)host).setWorkDir(new File(System.getProperty(Globals.CATALINA_HOME_PROP),
                "work" + File.separator + host.getName()).getAbsolutePath());

        return host;
    }

    private Host prepareVirtualHost(Tomcat tomcat, List<String> virtualHosts) {
        // assume that the first virtual-host will be the default; additional virtual-hosts will be aliases
        String hostName = virtualHosts.get(0);
        Host host;
        Engine engine = tomcat.getEngine();

        org.apache.catalina.Container childContainer = engine.findChild(hostName);
        if (childContainer instanceof Host) {
            host = (Host) childContainer;
        } else {
            host = new StandardHost();
            host.setName(hostName);
            engine.addChild(host);
        }

        virtualHosts.stream()
            .filter(virtualHost -> virtualHost != hostName)
            .forEach(virtualHost -> host.addAlias(virtualHost));

        return host;
    }

    private Property prepareTomcatClustering(Host host, Property engineConfig) throws ContainerException {
        Property clusterProp = null;

        List<Property> clusterProps = engineConfig.getPropertiesWithValue("cluster");
        if (clusterProps.size() > 1) {
            throw new ContainerException("Only one cluster configuration allowed per engine");
        }

        if (UtilValidate.isNotEmpty(clusterProps)) {
            clusterProp = clusterProps.get(0);

            GroupChannel channel = new GroupChannel();
            channel.setChannelReceiver(prepareChannelReceiver(clusterProp));
            channel.setChannelSender(prepareChannelSender(clusterProp));
            channel.setMembershipService(prepareChannelMcastService(clusterProp));

            SimpleTcpCluster cluster = new SimpleTcpCluster();
            cluster.setClusterName(clusterProp.name);
            cluster.setManagerTemplate(prepareClusterManager(clusterProp));
            cluster.setChannel(channel);
            cluster.addValve(prepareClusterValve(clusterProp));

            host.setCluster(cluster);

            Debug.logInfo("Catalina Cluster [" + cluster.getClusterName() + "] configured for host - " + host.getName(), module);
        }
        return clusterProp;
    }

    private NioReceiver prepareChannelReceiver(Property clusterProp) throws ContainerException {
        NioReceiver listener = new NioReceiver();

        String tla = ContainerConfig.getPropertyValue(clusterProp, "tcp-listen-host", "auto");
        int tlp = ContainerConfig.getPropertyValue(clusterProp, "tcp-listen-port", 4001);
        int tlt = ContainerConfig.getPropertyValue(clusterProp, "tcp-sector-timeout", 100);
        int tlc = ContainerConfig.getPropertyValue(clusterProp, "tcp-thread-count", 6);

        if (tlp == -1) {
            throw new ContainerException("Cluster configuration requires tcp-listen-port property");
        }

        listener.setAddress(tla);
        listener.setPort(tlp);
        listener.setSelectorTimeout(tlt);
        listener.setMaxThreads(tlc);
        listener.setMinThreads(tlc);

        return listener;
    }

    private ReplicationTransmitter prepareChannelSender(Property clusterProp) throws ContainerException {
        ReplicationTransmitter trans = new ReplicationTransmitter();
        try {
            MultiPointSender mps = (MultiPointSender)Class.forName(ContainerConfig.getPropertyValue(clusterProp,
                    "replication-mode", "org.apache.catalina.tribes.transport.bio.PooledMultiSender")).getDeclaredConstructor().newInstance();
            trans.setTransport(mps);
        } catch (Exception exc) {
            throw new ContainerException("Cluster configuration requires a valid replication-mode property: " + exc.getMessage());
        }
        return trans;
    }

    private McastService prepareChannelMcastService(Property clusterProp) throws ContainerException {
        McastService mcast = new McastService();

        String mcb = ContainerConfig.getPropertyValue(clusterProp, "mcast-bind-addr", null);
        String mca = ContainerConfig.getPropertyValue(clusterProp, "mcast-addr", null);
        int mcp = ContainerConfig.getPropertyValue(clusterProp, "mcast-port", -1);
        int mcf = ContainerConfig.getPropertyValue(clusterProp, "mcast-freq", 500);
        int mcd = ContainerConfig.getPropertyValue(clusterProp, "mcast-drop-time", 3000);

        if (mca == null || mcp == -1) {
            throw new ContainerException("Cluster configuration requires mcast-addr and mcast-port properties");
        }

        if (mcb != null) {
            mcast.setMcastBindAddress(mcb);
        }

        mcast.setAddress(mca);
        mcast.setPort(mcp);
        mcast.setMcastDropTime(mcd);
        mcast.setFrequency(mcf);

        return mcast;
    }

    private ClusterManager prepareClusterManager(Property clusterProp) throws ContainerException {
        String mgrClassName = ContainerConfig.getPropertyValue(clusterProp, "manager-class", "org.apache.catalina.ha.session.DeltaManager");
        try {
            return (ClusterManager)Class.forName(mgrClassName).getDeclaredConstructor().newInstance();
        } catch (ReflectiveOperationException e) {
            throw new ContainerException("Cluster configuration requires a valid manager-class property", e);
        }
    }

    private ReplicationValve prepareClusterValve(Property clusterProp) {
        ReplicationValve clusterValve = new ReplicationValve();
        String defaultValveFilter = ".*\\.gif;.*\\.js;.*\\.jpg;.*\\.htm;.*\\.html;.*\\.txt;.*\\.png;.*\\.css;.*\\.ico;.*\\.htc;";
        clusterValve.setFilter(ContainerConfig.getPropertyValue(clusterProp, "rep-valve-filter", defaultValveFilter));
        return clusterValve;
    }

    private List<Valve> prepareTomcatEngineValves(Property engineConfig) throws ContainerException {
        List<Valve> engineValves = new ArrayList<>();

        // configure the CrossSubdomainSessionValve
        if (ContainerConfig.getPropertyValue(engineConfig, "enable-cross-subdomain-sessions", false)) {
            engineValves.add(new CrossSubdomainSessionValve());
        }

        // configure the SslAcceleratorValve
        String sslAcceleratorPortStr = ContainerConfig.getPropertyValue(engineConfig, "ssl-accelerator-port", null);
        if (UtilValidate.isNotEmpty(sslAcceleratorPortStr)) {
            Integer sslAcceleratorPort = Integer.valueOf(sslAcceleratorPortStr);
            SslAcceleratorValve sslAcceleratorValve = new SslAcceleratorValve();
            sslAcceleratorValve.setSslAcceleratorPort(sslAcceleratorPort);
            engineValves.add(sslAcceleratorValve);
        }

        // configure the AccessLogValve
        String logDir = ContainerConfig.getPropertyValue(engineConfig, "access-log-dir", null);
        if (logDir != null) {
            AccessLogValve accessLogValve = new AccessLogValve();

            logDir = logDir.startsWith("/") ? System.getProperty("ofbiz.home") + "/" + logDir : logDir;
            File logFile = new File(logDir);
            if (!logFile.isDirectory()) {
                throw new ContainerException("Log directory [" + logDir + "] is not available; make sure the directory is created");
            }

            accessLogValve.setDirectory(logFile.getAbsolutePath());
            String accessLogPattern = ContainerConfig.getPropertyValue(engineConfig, "access-log-pattern", null);
            if (UtilValidate.isNotEmpty(accessLogPattern)) {
                accessLogValve.setPattern(accessLogPattern);
            }
            String accessLogPrefix = ContainerConfig.getPropertyValue(engineConfig, "access-log-prefix", null);
            if (UtilValidate.isNotEmpty(accessLogPrefix)) {
                accessLogValve.setPrefix(accessLogPrefix);
            }
            accessLogValve.setRotatable(ContainerConfig.getPropertyValue(engineConfig, "access-log-rotate", false));

            engineValves.add(accessLogValve);
        }

        return engineValves;
    }

    private List<Connector> prepareTomcatConnectors(Configuration configuration) throws ContainerException {
        List<Property> connectorProps = configuration.getPropertiesWithValue("connector");
        if (UtilValidate.isEmpty(connectorProps)) {
            throw new ContainerException("Cannot load CatalinaContainer; no connectors defined!");
        }
        return connectorProps.stream()
            .filter(connectorProp -> UtilValidate.isNotEmpty(connectorProp.properties))
            .map(connectorProp -> prepareConnector(connectorProp))
            .collect(Collectors.toList());
    }

    private Connector prepareConnector(Property connectorProp) {
        Connector connector = new Connector(ContainerConfig.getPropertyValue(connectorProp, "protocol", "HTTP/1.1"));
        connector.setPort(ContainerConfig.getPropertyValue(connectorProp, "port", 0) + Start.getInstance().getConfig().portOffset);

        connectorProp.properties.values().stream()
            .filter(prop -> !"protocol".equals(prop.name) && !"port".equals(prop.name))
            .forEach(prop -> {
                if (IntrospectionUtils.setProperty(connector, prop.name, prop.value)) {
                    if (prop.name.indexOf("Pass") != -1) {
                        // this property may be a password, do not include its value in the logs
                        Debug.logInfo("Tomcat " + connector + ": set " + prop.name, module);
                    } else {
                        Debug.logInfo("Tomcat " + connector + ": set " + prop.name + "=" + prop.value, module);
                    }
                } else {
                    Debug.logWarning("Tomcat " + connector + ": ignored parameter " + prop.name, module);
                }
            });
        return connector;
    }

    private void loadWebapps(Tomcat tomcat, ContainerConfig.Configuration configuration, Property clusterProp) {
        ScheduledExecutorService executor = ExecutionPool.getScheduledExecutor(new ThreadGroup(module),
                "catalina-startup", Runtime.getRuntime().availableProcessors(), 0, true);
        List<Future<Context>> futures = new ArrayList<>();

        List<ComponentConfig.WebappInfo> webResourceInfos = ComponentConfig.getAllWebappResourceInfos();
        Collections.reverse(webResourceInfos); // allow higher level webapps to override lower ones

        Set<String> webappsMounts = new HashSet<>();
        webResourceInfos.forEach(appInfo -> webappsMounts.addAll(getWebappMounts(appInfo)));

        for (ComponentConfig.WebappInfo appInfo: webResourceInfos) {
            if(webappsMounts.removeAll(getWebappMounts(appInfo))) {
                // webapp is not yet loaded
                if (!appInfo.location.isEmpty()) {
                    futures.add(executor.submit(createCallableContext(tomcat, appInfo, clusterProp, configuration)));
                }
            } else {
                /* webapp is loaded already (overridden). Therefore, disable
                 * app bar display on overridden apps and do not load */
                appInfo.setAppBarDisplay(false);
                Debug.logInfo("Duplicate webapp mount (overridding); not loading : " + appInfo.getName() + " / " + appInfo.getLocation(), module);
            }
        }
        ExecutionPool.getAllFutures(futures);
        executor.shutdown();
    }

    private List<String> getWebappMounts(ComponentConfig.WebappInfo webappInfo) {
        List<String> allAppsMounts = new ArrayList<>();
        String engineName = webappInfo.server;
        String mount = webappInfo.getContextRoot();
        List<String> virtualHosts = webappInfo.getVirtualHosts();
        if (virtualHosts.isEmpty()) {
            allAppsMounts.add(engineName + ":DEFAULT:" + mount);
        } else {
            virtualHosts.forEach(virtualHost -> allAppsMounts.add(engineName + ":" + virtualHost + ":" + mount));
        }
        return allAppsMounts;
    }

    private Callable<Context> createCallableContext(Tomcat tomcat, ComponentConfig.WebappInfo appInfo,
            Property clusterProp, ContainerConfig.Configuration configuration) {

        Debug.logInfo("Creating context [" + appInfo.name + "]", module);
        Host host = prepareHost(tomcat, appInfo.getVirtualHosts());

        return () -> {
            StandardContext context = prepareContext(host, configuration, appInfo, clusterProp);
            Debug.logInfo("host[" + host + "].addChild(" + context + ")", module);
            host.addChild(context);
            return context;
        };
    }

    private StandardContext prepareContext(Host host, ContainerConfig.Configuration configuration,
            ComponentConfig.WebappInfo appInfo, Property clusterProp) throws ContainerException {

        StandardContext context = new StandardContext();
        Tomcat.initWebappDefaults(context);

        String location = getWebappRootLocation(appInfo);
        boolean contextIsDistributable = isContextDistributable(configuration, appInfo);

        context.setParent(host);
        context.setDocBase(location);
        context.setDisplayName(appInfo.name);
        context.setPath(getWebappMountPoint(appInfo));
        context.addLifecycleListener(new ContextConfig());
        context.setJ2EEApplication("OFBiz");
        context.setJ2EEServer("OFBiz Container");
        context.setParentClassLoader(Thread.currentThread().getContextClassLoader());
        context.setDocBase(location);
        context.setReloadable(ContainerConfig.getPropertyValue(configuration, "apps-context-reloadable", false));
        context.setDistributable(contextIsDistributable);
        context.setCrossContext(ContainerConfig.getPropertyValue(configuration, "apps-cross-context", true));
        context.setPrivileged(appInfo.privileged);
        context.getServletContext().setAttribute("_serverId", appInfo.server);
        context.getServletContext().setAttribute("componentName", appInfo.componentConfig.getComponentName());

        if (clusterProp != null && contextIsDistributable) {
            context.setManager(prepareClusterManager(clusterProp));
        }

        StandardRoot resources = new StandardRoot(context);
        resources.setAllowLinking(true);
        context.setResources(resources);

        JarScanner jarScanner = context.getJarScanner();
        if (jarScanner instanceof StandardJarScanner) {
            StandardJarScanner standardJarScanner = (StandardJarScanner) jarScanner;
            standardJarScanner.setJarScanFilter(new FilterJars());
            standardJarScanner.setScanClassPath(true);
        }

        Map<String, String> initParameters = appInfo.getInitParameters();
        // request dumper filter
        if ("true".equals(initParameters.get("enableRequestDump"))) {
            FilterDef requestDumperFilterDef = new FilterDef();
            requestDumperFilterDef.setFilterClass(RequestDumperFilter.class.getName());
            requestDumperFilterDef.setFilterName("RequestDumper");
            context.addFilterDef(requestDumperFilterDef);

            FilterMap requestDumperFilterMap = new FilterMap();
            requestDumperFilterMap.setFilterName("RequestDumper");
            requestDumperFilterMap.addURLPattern("*");
            context.addFilterMap(requestDumperFilterMap);
        }

        // set the init parameters
        initParameters.entrySet().forEach(entry -> context.addParameter(entry.getKey(), entry.getValue()));

        return context;
    }

    private String getWebappRootLocation(ComponentConfig.WebappInfo appInfo) {
        String location = appInfo.componentConfig.getRootLocation() + appInfo.location;
        location = location.replace('\\', '/');
        if (location.endsWith("/")) {
            location = location.substring(0, location.length() - 1);
        }
        return location;
    }

    private String getWebappMountPoint(ComponentConfig.WebappInfo appInfo) {
        String mount = appInfo.mountPoint;
        if (mount.endsWith("/*")) {
            mount = mount.substring(0, mount.length() - 2);
        }
        return mount;
    }

    private static boolean isContextDistributable(ContainerConfig.Configuration configuration,
            ComponentConfig.WebappInfo appInfo) throws ContainerException {
        boolean appIsDistributable = ContainerConfig.getPropertyValue(configuration, "apps-distributable", true);
        try {
            boolean isDistributable = WebAppUtil.isDistributable(appInfo);
            return appIsDistributable && isDistributable;
        } catch (SAXException | IOException e) {
            throw new ContainerException(e);
        }
    }
}
