/*
 * Copyright (c) 2009, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.kernel.javaee;

import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.ConfigBeansUtilities;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.HttpService;
import com.sun.enterprise.config.serverbeans.VirtualServer;
import com.sun.enterprise.module.ModulesRegistry;
import com.sun.enterprise.v3.server.ContainerStarter;
import java.beans.PropertyChangeEvent;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.inject.Provider;
import org.glassfish.api.StartupRunLevel;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.container.Sniffer;
import org.glassfish.grizzly.config.dom.NetworkConfig;
import org.glassfish.grizzly.config.dom.NetworkListener;
import org.glassfish.grizzly.config.dom.NetworkListeners;
import org.glassfish.hk2.api.PostConstruct;
import org.glassfish.hk2.runlevel.RunLevel;
import org.glassfish.internal.data.ContainerRegistry;
import org.glassfish.internal.data.EngineInfo;
import org.glassfish.logging.annotation.LogMessageInfo;
import org.glassfish.logging.annotation.LogMessagesResourceBundle;
import org.glassfish.logging.annotation.LoggerInfo;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.config.Changed;
import org.jvnet.hk2.config.ConfigBeanProxy;
import org.jvnet.hk2.config.ConfigListener;
import org.jvnet.hk2.config.ConfigSupport;
import org.jvnet.hk2.config.NotProcessed;
import org.jvnet.hk2.config.ObservableBean;
import org.jvnet.hk2.config.UnprocessedChangeEvents;
import org.jvnet.hk2.config.types.Property;

/**
 * Startup service for the web container.
 *
 * This service checks if any domain.xml configuration, or changes in
 * such configuration, that can be handled only by the web container
 * (e.g., access logging) have been specified, and if so, starts the
 * web container (unless already started).
 *
 * @author jluehe
 */
@Service
@RunLevel(StartupRunLevel.VAL)
public class WebContainerStarter
        implements PostConstruct, ConfigListener {

    private static final String LOGMSG_PREFIX = "AS-CORE-JAVAEE";

    @LogMessagesResourceBundle
    private static final String SHARED_LOGMESSAGE_RESOURCE = "org.glassfish.kernel.javaee.LogMessages";

    @LoggerInfo(subsystem = "AS-CORE", description = "Java EE Core Kernel", publish = true)
    private static final String ASCORE_LOGGER = "jakarta.enterprise.system.core.ee";
    private static final Logger logger = Logger.getLogger(
                ASCORE_LOGGER, SHARED_LOGMESSAGE_RESOURCE);
    private static final ResourceBundle rb = logger.getResourceBundle();

    @LogMessageInfo(
            message = "Web Container not installed",
            cause = "The web container does not install properly.",
            action = "Please check the web container libraries are installed properly.",
            level = "INFO")
    public static final String mWebContainerNotInstalled = LOGMSG_PREFIX + "-0001";

    @LogMessageInfo(
            message = "Done with starting {0} container.",
            level = "INFO")
    public static final String mStartContainerDone = LOGMSG_PREFIX + "-0002";

    @LogMessageInfo(
            message = "Unable to start container (no exception provided)",
            cause = "The web container does not start properly.",
            action = "Please check the web container libraries are installed properly.",
            level = "SEVERE")
    public static final String mUnableStartContainerNoException = LOGMSG_PREFIX + "-0003";

    @LogMessageInfo(
            message = "Unable to start container {0}",
            cause = "The web container does not start properly. Most probably, there is a class loading issue.",
            action = "Please resolve issues mentioned in the stack trace.",
            level = "SEVERE")
    public static final String mUnableStartContainer = LOGMSG_PREFIX + "-0004";

    private static final String AUTH_PASSTHROUGH_ENABLED_PROP =
        "authPassthroughEnabled";

    private static final String PROXY_HANDLER_PROP = "proxyHandler";

    private static final String TRACE_ENABLED_PROP = "traceEnabled";

    @Inject
    private Provider<Domain> domainProvider;

    @Inject
    private ContainerRegistry containerRegistry;

    @Inject
    private ContainerStarter containerStarter;

    @Inject
    private ModulesRegistry modulesRegistry;

    @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
    private Provider<Config> serverConfigProvider;

    @Inject @Named("web")
    private Provider<Sniffer> webSnifferProvider;

    /**
     * Scans the domain.xml to see if it specifies any configuration
     * that can be handled only by the web container, and if so, starts
     * the web container
     */
    public void postConstruct() {
        domainProvider.get();
        Config serverConfig = serverConfigProvider.get();

        boolean isStartNeeded = false;
        if (serverConfig != null) {
            if (isStartNeeded(serverConfig.getHttpService())) {
                isStartNeeded = true;
            }
            if (!isStartNeeded && isStartNeeded(serverConfig.getNetworkConfig())) {
                isStartNeeded = true;
            }
        }

        if (isStartNeeded) {
            startWebContainer();
        } else {
            ObservableBean bean = (ObservableBean) ConfigSupport.getImpl(serverConfig.getHttpService());
            bean.addListener(this);
            bean = (ObservableBean) ConfigSupport.getImpl(serverConfig.getNetworkConfig().getNetworkListeners());
            bean.addListener(this);
        }
    }

    public UnprocessedChangeEvents changed(PropertyChangeEvent[] events) {
        return ConfigSupport.sortAndDispatch(events, new Changed() {
            public <T extends ConfigBeanProxy> NotProcessed changed(
                    TYPE type, Class<T> tClass, T t) {
                if (tClass == HttpService.class) {
                    if (type == TYPE.CHANGE) {
                        if (isStartNeeded((HttpService) t)) {
                            startWebContainer();
                        }
                    }
                } else if (tClass == VirtualServer.class) {
                    if (type == TYPE.ADD || type == TYPE.CHANGE) {
                        if (isStartNeeded((VirtualServer) t)) {
                            startWebContainer();
                        }
                    }
                } else if (tClass == NetworkListener.class) {
                    if (type == TYPE.ADD || type == TYPE.CHANGE) {
                        if (isStartNeeded((NetworkListener) t)) {
                            startWebContainer();
                        }
                    }
                }
                return null;
            }
        }
        , logger);
    }

    /**
     * Starts the web container
     */
    private void startWebContainer() {
        Sniffer webSniffer = webSnifferProvider.get();
        if (webSniffer==null) {
            if (logger.isLoggable(Level.INFO)) {
                logger.info(mWebContainerNotInstalled);
            }
            return;
        }

        if (containerRegistry.getContainer(
                    webSniffer.getContainersNames()[0]) != null) {
            containerRegistry.getContainer(
                    webSniffer.getContainersNames()[0]).getContainer();
        } else {
            try {
                Collection<EngineInfo> containersInfo =
                    containerStarter.startContainer(webSniffer);
                if (containersInfo != null && !containersInfo.isEmpty()) {
                    // Start each container
                    for (EngineInfo info : containersInfo) {
                        info.getContainer();
                        if (logger.isLoggable(Level.INFO)) {
                            logger.log(Level.INFO, mStartContainerDone,
                                webSniffer.getModuleType());
                        }
                    }
                } else {
                    logger.severe(mUnableStartContainerNoException);
                }
            } catch (Exception e) {
                String msg;
                if ( rb != null ) {
                    msg = MessageFormat.format( rb.getString(mUnableStartContainer), webSniffer.getContainersNames()[0]);
                } else {
                    msg = "Unable to start Web Container: " + webSniffer.getContainersNames()[0];
                }
                logger.log(Level.SEVERE, msg, e);
            }
        }
    }

    /*
     * @return true if the given HttpService contains any configuration
     * that can be handled only by the web container and therefore requires
     * the web container to be started, false otherwise
     */
    private boolean isStartNeeded(HttpService httpService) {
        if (httpService == null) {
            return false;
        }

        if (ConfigBeansUtilities.toBoolean(
                    httpService.getAccessLoggingEnabled()) ||
                ConfigBeansUtilities.toBoolean(
                    httpService.getSsoEnabled())) {
            return true;
        }

        List<Property> props = httpService.getProperty();
        if (props != null) {
            for (Property prop : props) {
                String propName = prop.getName();
                String propValue = prop.getValue();
                if (AUTH_PASSTHROUGH_ENABLED_PROP.equals(propName)) {
                    if (ConfigBeansUtilities.toBoolean(propValue)) {
                        return true;
                    }
                } else if (PROXY_HANDLER_PROP.equals(propName)) {
                    return true;
                } else if (TRACE_ENABLED_PROP.equals(propName)) {
                    if (!ConfigBeansUtilities.toBoolean(propValue)) {
                        return true;
                    }
                }
            }
        }

        List<VirtualServer> hosts = httpService.getVirtualServer();
        if (hosts != null) {
            for (VirtualServer host : hosts) {
                if (isStartNeeded(host)) {
                    return true;
                }
            }
        }

        return false;
    }

    /*
     * @return true if the given VirtualServer contains any configuration
     * that can be handled only by the web container and therefore requires
     * the web container to be started, false otherwise
     */
    private boolean isStartNeeded(VirtualServer host) {
        if (host == null) {
            return false;
        }

        if (ConfigBeansUtilities.toBoolean(host.getAccessLoggingEnabled()) ||
                ConfigBeansUtilities.toBoolean(host.getSsoEnabled())) {
            return true;
        }

        String state = host.getState();
        if (state != null &&
                ("disabled".equals(state) ||
                    !ConfigBeansUtilities.toBoolean(state))) {
            return true;
        }

        List<Property> props = host.getProperty();
        if (props != null && !props.isEmpty()) {
            return true;
        }

        return false;
    }

    /*
     * @return true if the given NetworkConfig contains any configuration
     * that can be handled only by the web container and therefore requires
     * the web container to be started, false otherwise
     */
    private boolean isStartNeeded(NetworkConfig networkConfig) {
        if (networkConfig == null) {
            return false;
        }

        NetworkListeners networkListeners = networkConfig.getNetworkListeners();
        if (networkListeners == null) {
            return false;
        }

        for (NetworkListener networkListener : networkListeners.getNetworkListener()) {
            if (isStartNeeded(networkListener)) {
                return true;
            }
        }

        return false;
    }

    /*
     * @return true if the given NetworkListener contains any configuration
     * that can be handled only by the web container and therefore requires
     * the web container to be started, false otherwise
     */
    private boolean isStartNeeded(NetworkListener networkListener) {
        if (networkListener == null) {
            return false;
        }

        return ConfigBeansUtilities.toBoolean(networkListener.getJkEnabled());
    }
}
