/*
 * 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.geode.internal.cache;

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.WebAppContext;

import org.apache.geode.annotations.VisibleForTesting;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.internal.HttpService;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.internal.admin.SSLConfig;
import org.apache.geode.internal.net.SSLConfigurationFactory;
import org.apache.geode.internal.security.SecurableCommunicationChannel;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.management.internal.SSLUtil;
import org.apache.geode.management.internal.beans.CacheServiceMBeanBase;

public class InternalHttpService implements HttpService {

  private static final Logger logger = LogService.getLogger();
  private Server httpServer;
  private String bindAddress = "0.0.0.0";
  private int port;
  private static final String FILE_PATH_SEPARATOR = System.getProperty("file.separator");
  private static final String USER_DIR = System.getProperty("user.dir");
  private static final String USER_NAME = System.getProperty("user.name");

  private static final String HTTPS = "https";

  private List<WebAppContext> webApps = new ArrayList<>();

  @Override
  public boolean init(Cache cache) {
    InternalDistributedSystem distributedSystem =
        (InternalDistributedSystem) cache.getDistributedSystem();
    DistributionConfig systemConfig = distributedSystem.getConfig();

    if (((InternalCache) cache).isClient()) {
      return false;
    }

    if (systemConfig.getHttpServicePort() == 0) {
      logger.info("HttpService is disabled with http-service-port = 0");
      return false;
    }

    try {
      createJettyServer(systemConfig.getHttpServiceBindAddress(),
          systemConfig.getHttpServicePort(),
          SSLConfigurationFactory.getSSLConfigForComponent(systemConfig,
              SecurableCommunicationChannel.WEB));
    } catch (Throwable ex) {
      logger.warn("Could not enable HttpService: {}", ex.getMessage());
      return false;
    }

    return true;
  }

  @VisibleForTesting
  public void createJettyServer(String bindAddress, int port, SSLConfig sslConfig) {
    this.httpServer = new Server();

    // Add a handler collection here, so that each new context adds itself
    // to this collection.
    httpServer.setHandler(new HandlerCollection(true));
    ServerConnector connector = null;

    HttpConfiguration httpConfig = new HttpConfiguration();
    httpConfig.setSecureScheme(HTTPS);
    httpConfig.setSecurePort(port);

    if (sslConfig.isEnabled()) {
      SslContextFactory sslContextFactory = new SslContextFactory.Server();

      if (StringUtils.isNotBlank(sslConfig.getAlias())) {
        sslContextFactory.setCertAlias(sslConfig.getAlias());
      }

      sslContextFactory.setNeedClientAuth(sslConfig.isRequireAuth());

      if (StringUtils.isNotBlank(sslConfig.getCiphers())
          && !"any".equalsIgnoreCase(sslConfig.getCiphers())) {
        sslContextFactory.setExcludeCipherSuites();
        sslContextFactory.setIncludeCipherSuites(SSLUtil.readArray(sslConfig.getCiphers()));
      }

      sslContextFactory.setSslContext(SSLUtil.createAndConfigureSSLContext(sslConfig, false));

      if (logger.isDebugEnabled()) {
        logger.debug(sslContextFactory.dump());
      }
      httpConfig.addCustomizer(new SecureRequestCustomizer());

      // Somehow With HTTP_2.0 Jetty throwing NPE. Need to investigate further whether all GemFire
      // web application(Pulse, REST) can do with HTTP_1.1
      connector = new ServerConnector(httpServer,
          new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
          new HttpConnectionFactory(httpConfig));

      connector.setPort(port);
    } else {
      connector = new ServerConnector(httpServer, new HttpConnectionFactory(httpConfig));

      connector.setPort(port);
    }

    httpServer.setConnectors(new Connector[] {connector});

    if (StringUtils.isNotBlank(bindAddress)) {
      connector.setHost(bindAddress);
    }

    if (bindAddress != null && !bindAddress.isEmpty()) {
      this.bindAddress = bindAddress;
    }
    this.port = port;

    logger.info("Enabled InternalHttpService on port {}", port);
  }

  @Override
  public Class<? extends CacheService> getInterface() {
    return HttpService.class;
  }

  @Override
  public CacheServiceMBeanBase getMBean() {
    return null;
  }

  public Server getHttpServer() {
    return httpServer;
  }

  @Override
  public synchronized void addWebApplication(String webAppContext, Path warFilePath,
      Map<String, Object> attributeNameValuePairs)
      throws Exception {
    if (httpServer == null) {
      logger.info(
          String.format("unable to add %s webapp. Http service is not started on this member.",
              webAppContext));
      return;
    }

    WebAppContext webapp = new WebAppContext();
    webapp.setContextPath(webAppContext);
    webapp.setWar(warFilePath.toString());
    webapp.setParentLoaderPriority(false);

    // GEODE-7334: load all jackson classes from war file except jackson annotations
    webapp.getSystemClasspathPattern().add("com.fasterxml.jackson.annotation.");
    webapp.getServerClasspathPattern().add("com.fasterxml.jackson.",
        "-com.fasterxml.jackson.annotation.");

    webapp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
    webapp.addAliasCheck(new AllowSymLinkAliasChecker());

    if (attributeNameValuePairs != null) {
      attributeNameValuePairs.forEach((key, value) -> webapp.setAttribute(key, value));
    }

    File tmpPath = new File(getWebAppBaseDirectory(webAppContext));
    tmpPath.mkdirs();
    webapp.setTempDirectory(tmpPath);
    logger.info("Adding webapp " + webAppContext);
    ((HandlerCollection) httpServer.getHandler()).addHandler(webapp);

    // if the server is not started yet start the server, otherwise, start the webapp alone
    if (!httpServer.isStarted()) {
      logger.info("Attempting to start HTTP service on port ({}) at bind-address ({})...",
          this.port, this.bindAddress);
      httpServer.start();
    } else {
      webapp.start();
    }
    webApps.add(webapp);
  }

  private String getWebAppBaseDirectory(final String context) {
    String underscoredContext = context.replace("/", "_");
    String uuid = UUID.randomUUID().toString().substring(0, 8);
    final String workingDirectory = USER_DIR.concat(FILE_PATH_SEPARATOR)
        .concat("GemFire_" + USER_NAME).concat(FILE_PATH_SEPARATOR).concat("services")
        .concat(FILE_PATH_SEPARATOR).concat("http").concat(FILE_PATH_SEPARATOR)
        .concat((StringUtils.isBlank(bindAddress)) ? "0.0.0.0" : bindAddress).concat("_")
        .concat(String.valueOf(port).concat(underscoredContext)).concat("_").concat(uuid);

    return workingDirectory;
  }

  @Override
  public void close() {
    if (this.httpServer == null) {
      return;
    }

    logger.debug("Stopping the HTTP service...");
    try {
      for (WebAppContext webapp : webApps) {
        webapp.stop();
      }
      this.httpServer.stop();
    } catch (Exception e) {
      logger.warn("Failed to stop the HTTP service because: {}", e.getMessage(), e);
    } finally {
      try {
        this.httpServer.destroy();
      } catch (Exception ignore) {
        logger.info("Failed to properly release resources held by the HTTP service: {}",
            ignore.getMessage(), ignore);
      } finally {
        this.httpServer = null;
        System.clearProperty("catalina.base");
        System.clearProperty("catalina.home");
      }
    }
  }
}
