/*
 * 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.storm.daemon.ui;

import static org.apache.storm.utils.ConfigUtils.FILE_SEPARATOR;
import static org.apache.storm.utils.ConfigUtils.STORM_HOME;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import javax.servlet.DispatcherType;
import org.apache.storm.DaemonConfig;
import org.apache.storm.daemon.drpc.webapp.ReqContextFilter;
import org.apache.storm.daemon.ui.exceptionmappers.AuthorizationExceptionMapper;
import org.apache.storm.daemon.ui.exceptionmappers.DefaultExceptionMapper;
import org.apache.storm.daemon.ui.exceptionmappers.NotAliveExceptionMapper;
import org.apache.storm.daemon.ui.filters.AuthorizedUserFilter;
import org.apache.storm.daemon.ui.filters.HeaderResponseFilter;
import org.apache.storm.daemon.ui.filters.HeaderResponseServletFilter;
import org.apache.storm.metric.StormMetricsRegistry;
import org.apache.storm.security.auth.IHttpCredentialsPlugin;
import org.apache.storm.security.auth.ServerAuthUtils;
import org.apache.storm.utils.ConfigUtils;
import org.apache.storm.utils.ObjectReader;
import org.apache.storm.utils.Utils;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Main class.
 *
 */
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
public class UIServer {

    public static final Logger LOG = LoggerFactory.getLogger(UIServer.class);

    public static final String STORM_API_URL_PREFIX = "/api/v1/";

    /**
     * addRequestContextFilter.
     * @param context context
     * @param configName configName
     * @param conf conf
     */
    public static void addRequestContextFilter(ServletContextHandler context,
                                               String configName, Map<String, Object> conf) {
        IHttpCredentialsPlugin auth = ServerAuthUtils.getHttpCredentialsPlugin(conf, (String) conf.get(configName));
        ReqContextFilter filter = new ReqContextFilter(auth);
        context.addFilter(new FilterHolder(filter), "/*", EnumSet.allOf(DispatcherType.class));
    }

    /**
     * main.
     * @param args args
     */
    public static void main(String[] args) {

        Map<String, Object> conf = ConfigUtils.readStormConfig();
        int headerBufferSize = (int) conf.get(DaemonConfig.UI_HEADER_BUFFER_BYTES);
        final Integer httpsPort = ObjectReader.getInt(conf.get(DaemonConfig.UI_HTTPS_PORT), 0);
        final String httpsKsPath = (String) (conf.get(DaemonConfig.UI_HTTPS_KEYSTORE_PATH));
        final String httpsKsPassword = (String) (conf.get(DaemonConfig.UI_HTTPS_KEYSTORE_PASSWORD));
        final String httpsKsType = (String) (conf.get(DaemonConfig.UI_HTTPS_KEYSTORE_TYPE));
        final String httpsKeyPassword = (String) (conf.get(DaemonConfig.UI_HTTPS_KEY_PASSWORD));
        final String httpsTsPath = (String) (conf.get(DaemonConfig.UI_HTTPS_TRUSTSTORE_PATH));
        final String httpsTsPassword = (String) (conf.get(DaemonConfig.UI_HTTPS_TRUSTSTORE_PASSWORD));
        final String httpsTsType = (String) (conf.get(DaemonConfig.UI_HTTPS_TRUSTSTORE_TYPE));
        final Boolean httpsWantClientAuth = (Boolean) (conf.get(DaemonConfig.UI_HTTPS_WANT_CLIENT_AUTH));
        final Boolean httpsNeedClientAuth = (Boolean) (conf.get(DaemonConfig.UI_HTTPS_NEED_CLIENT_AUTH));
        final Boolean disableHttpBinding = (Boolean) (conf.get(DaemonConfig.UI_DISABLE_HTTP_BINDING));

        Server jettyServer =
                UIHelpers.jettyCreateServer(
                        (int) conf.get(DaemonConfig.UI_PORT), null, httpsPort, headerBufferSize, disableHttpBinding);

        UIHelpers.configSsl(jettyServer, httpsPort, httpsKsPath, httpsKsPassword, httpsKsType, httpsKeyPassword,
                httpsTsPath, httpsTsPassword, httpsTsType, httpsNeedClientAuth, httpsWantClientAuth);

        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        jettyServer.setHandler(context);

        FilterConfiguration filterConfiguration =
                new FilterConfiguration(
                        (String) conf.get(DaemonConfig.UI_FILTER),
                        (Map<String, String>) conf.get(DaemonConfig.UI_FILTER_PARAMS)
                );
        final List<FilterConfiguration> filterConfigurationList = Arrays.asList(filterConfiguration);

        UIHelpers.configFilters(context, filterConfigurationList);

        StormMetricsRegistry metricsRegistry = new StormMetricsRegistry();
        ResourceConfig resourceConfig =
            new ResourceConfig()
                .packages("org.apache.storm.daemon.ui.resources")
                .registerInstances(new AbstractBinder() {
                    @Override
                    protected void configure() {
                        super.bind(metricsRegistry).to(StormMetricsRegistry.class);
                    }
                })
                .register(AuthorizedUserFilter.class)
                .register(HeaderResponseFilter.class)
                .register(AuthorizationExceptionMapper.class)
                .register(NotAliveExceptionMapper.class)
                .register(DefaultExceptionMapper.class);

        ServletHolder jerseyServlet = new ServletHolder(new ServletContainer(resourceConfig));
        jerseyServlet.setInitOrder(0);
        context.addServlet(jerseyServlet, STORM_API_URL_PREFIX + "*");
        addRequestContextFilter(context, DaemonConfig.UI_HTTP_CREDS_PLUGIN, conf);


        // add special pathspec of static content mapped to the homePath
        ServletHolder holderHome = new ServletHolder("static-home", DefaultServlet.class);

        String packagedStaticFileLocation = System.getProperty(STORM_HOME) + FILE_SEPARATOR + "public/";

        if (Files.exists(Paths.get(packagedStaticFileLocation))) {
            holderHome.setInitParameter("resourceBase", packagedStaticFileLocation);
        } else {
            LOG.warn("Cannot find static file directory in " +  packagedStaticFileLocation
                    + " - assuming that UIServer is being launched"
                    + "in a development environment and not from a packaged release");
            String developmentStaticFileLocation =
                    UIServer.class.getProtectionDomain().getCodeSource().getLocation().getPath()
                            + "WEB-INF";
            if (Files.exists(Paths.get(developmentStaticFileLocation))) {
                holderHome.setInitParameter("resourceBase", developmentStaticFileLocation);
            } else {
                throw new RuntimeException("Cannot find static file directory in development "
                        + "location " + developmentStaticFileLocation);
            }
        }

        holderHome.setInitParameter("dirAllowed","true");
        holderHome.setInitParameter("pathInfoOnly","true");
        context.addFilter(new FilterHolder(new HeaderResponseServletFilter(metricsRegistry)), "/*", EnumSet.allOf(DispatcherType.class));
        context.addServlet(holderHome,"/*");


        // Lastly, the default servlet for root content (always needed, to satisfy servlet spec)
        ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class);
        holderPwd.setInitParameter("dirAllowed","true");
        context.addServlet(holderPwd,"/");

        metricsRegistry.startMetricsReporters(conf);
        Utils.addShutdownHookWithForceKillIn1Sec(metricsRegistry::stopMetricsReporters);
        try {
            jettyServer.start();
            jettyServer.join();
        } catch (Throwable t) {
            LOG.error("Exception in UIServer: ", t);
            throw new RuntimeException(t);
        }

    }
}

