/*
 * 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.knox.gateway.shell;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.security.auth.callback.TextCallbackHandler;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.auth.AuthSchemeProvider;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.auth.SPNegoSchemeFactory;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.shell.util.ClientTrustStoreHelper;
import org.apache.knox.gateway.util.JsonUtils;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.security.auth.Subject;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.channels.OverlappingFileLockException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.security.AccessController;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import de.thetaphi.forbiddenapis.SuppressForbidden;

public class KnoxSession implements Closeable {
  private static final String DEFAULT_JAAS_FILE = "/jaas.conf";
  public static final String JGSS_LOGIN_MOUDLE = "com.sun.security.jgss.initiate";
  public static final String END_CERTIFICATE = "-----END CERTIFICATE-----\n";
  public static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n";

  private static final KnoxShellMessages LOG = MessagesFactory.get(KnoxShellMessages.class);

  private static final CredentialsProvider EMPTY_CREDENTIALS_PROVIDER = new BasicCredentialsProvider();
  static {
    EMPTY_CREDENTIALS_PROVIDER.setCredentials(AuthScope.ANY,
                                                new Credentials() {
                                                  @Override
                                                  public Principal getUserPrincipal () {
                                                    return null;
                                                  }

                                                  @Override
                                                  public String getPassword () {
                                                    return null;
                                                  }
                                                });
  }

  private boolean isKerberos;

  private URL jaasConfigURL;

  String base;
  HttpHost host;
  CloseableHttpClient client;
  BasicHttpContext context;
  ExecutorService executor;
  Map<String, String> headers = new HashMap<>();

  private static final String KNOXSQLHISTORIES_JSON = "knoxsqlhistories.json";
  private static final String KNOXDATASOURCES_JSON = "knoxdatasources.json";

  public Map<String, String> getHeaders() {
    return headers;
  }

  public void setHeaders(Map<String, String> headers) {
    this.headers = headers;
  }

  protected KnoxSession() throws KnoxShellException, URISyntaxException {
  }

  public KnoxSession(final ClientContext clientContext) throws KnoxShellException, URISyntaxException {
    this.executor = Executors.newCachedThreadPool();
    this.base = clientContext.url();

    try {
      client = createClient(clientContext);
    } catch (GeneralSecurityException e) {
      throw new KnoxShellException("Failed to create HTTP client.", e);
    }
  }

  public static KnoxSession login( String url, Map<String,String> headers ) throws URISyntaxException {
    KnoxSession instance = new KnoxSession(ClientContext.with(url));
    instance.setHeaders(headers);
    return instance;
  }

  public static KnoxSession login( String             url,
                                   Map<String,String> headers,
                                   String             truststoreLocation,
                                   String             truststorePass  ) throws URISyntaxException {
    KnoxSession instance = new KnoxSession(ClientContext.with(url)
                                                        .connection()
                                                        .withTruststore(truststoreLocation, truststorePass)
                                                        .end());
    instance.setHeaders(headers);
    return instance;
  }

  public static KnoxSession login( String url, String username, String password ) throws URISyntaxException {
    return new KnoxSession(ClientContext.with(username, password, url));
  }

  public static KnoxSession login( String url, String username, String password,
      String truststoreLocation, String truststorePass ) throws URISyntaxException {

    return new KnoxSession(ClientContext.with(username, password, url)
        .connection().withTruststore(truststoreLocation, truststorePass).end());
  }

  public static KnoxSession login(ClientContext context) throws URISyntaxException {
    return new KnoxSession(context);
  }

  /**
   * Support kerberos authentication.
   *
   * @param url Gateway url
   * @param jaasConf jaas configuration (optional- can be null)
   * @param krb5Conf kerberos configuration (optional - can be null)
   * @param debug enable debug messages
   * @return KnoxSession
   * @throws URISyntaxException exception in case of malformed url
   * @since 1.3.0
   */
  public static KnoxSession kerberosLogin(final String url,
      final String jaasConf,
      final String krb5Conf,
      final boolean debug)
      throws URISyntaxException {

    return new KnoxSession(ClientContext.with(url)
        .kerberos()
        .enable(true)
        .jaasConf(jaasConf)
        .krb5Conf(krb5Conf)
        .debug(debug)
        .end());
  }

  /**
   * Support kerberos authentication.
   * This method assumed kinit has already been called
   * and the token is persisted on disk.
   * @param url Gateway url
   * @return KnoxSession
   * @throws URISyntaxException exception in case of malformed url
   * @since 1.3.0
   */
  public static KnoxSession kerberosLogin(final String url)
      throws URISyntaxException {
    return kerberosLogin(url, false);
  }

  /**
   * Support kerberos authentication.
   * This method assumed kinit has already been called
   * and the token is persisted on disk.
   * @param url Gateway url
   * @param debug enable debug messages
   * @return KnoxSession
   * @throws URISyntaxException exception in case of malformed url
   * @since 1.3.0
   */
  public static KnoxSession kerberosLogin(final String url, boolean debug)
      throws URISyntaxException {
    return kerberosLogin(url, "", "", debug);
  }

  public static KnoxSession loginInsecure(String url, String username, String password) throws URISyntaxException {
    return new KnoxSession(ClientContext.with(username, password, url)
        .connection().secure(false).end());
  }

  @SuppressForbidden
  protected CloseableHttpClient createClient(ClientContext clientContext) throws GeneralSecurityException {

    // SSL
    HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
    TrustStrategy trustStrategy = null;
    if (clientContext.connection().secure()) {
      hostnameVerifier = SSLConnectionSocketFactory.getDefaultHostnameVerifier();
    } else {
      trustStrategy = TrustSelfSignedStrategy.INSTANCE;
      System.out.println("**************** WARNING ******************\n"
          + "This is an insecure client instance and may\n"
          + "leave the interactions subject to a man in\n"
          + "the middle attack. Please use the login()\n"
          + "method instead of loginInsecure() for any\n"
          + "sensitive or production usecases.\n"
          + "*******************************************");
    }

    KeyStore trustStore = getTrustStore(clientContext);
    SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStore, trustStrategy).build();
    Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.getSocketFactory())
        .register("https", new SSLConnectionSocketFactory(sslContext, hostnameVerifier)).build();

    // Pool
    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
    connectionManager.setMaxTotal(clientContext.pool().maxTotal());
    connectionManager.setDefaultMaxPerRoute(clientContext.pool().defaultMaxPerRoute());

    ConnectionConfig connectionConfig = ConnectionConfig.custom()
        .setBufferSize(clientContext.connection().bufferSize())
        .build();
    connectionManager.setDefaultConnectionConfig(connectionConfig);

    SocketConfig socketConfig = SocketConfig.custom()
        .setSoKeepAlive(clientContext.socket().keepalive())
        .setSoLinger(clientContext.socket().linger())
        .setSoReuseAddress(clientContext.socket().reuseAddress())
        .setSoTimeout(clientContext.socket().timeout())
        .setTcpNoDelay(clientContext.socket().tcpNoDelay())
        .build();
    connectionManager.setDefaultSocketConfig(socketConfig);

    // Auth
    URI uri = URI.create(clientContext.url());
    host = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());

    /* kerberos auth */
    if (clientContext.kerberos().enable()) {
      isKerberos = true;
      /* set up system properties */
      if (!StringUtils.isBlank(clientContext.kerberos().krb5Conf())) {
        System.setProperty("java.security.krb5.conf",
            clientContext.kerberos().krb5Conf());
      }

      if (!StringUtils.isBlank(clientContext.kerberos().jaasConf())) {
        File f = new File(clientContext.kerberos().jaasConf());
        if (f.exists()) {
          try {
            jaasConfigURL = f.getCanonicalFile().toURI().toURL();
            LOG.jaasConfigurationLocation(jaasConfigURL.toExternalForm());
          } catch (IOException e) {
            LOG.failedToLocateJAASConfiguration(e.getMessage());
          }
        } else {
          LOG.jaasConfigurationDoesNotExist(f.getAbsolutePath());
        }
      }

      // Fall back to the default JAAS config
      if (jaasConfigURL == null) {
        LOG.usingDefaultJAASConfiguration();
        jaasConfigURL = getClass().getResource(DEFAULT_JAAS_FILE);
        LOG.jaasConfigurationLocation(jaasConfigURL.toExternalForm());
      }

      if (clientContext.kerberos().debug()) {
        System.setProperty("sun.security.krb5.debug", "true");
        System.setProperty("sun.security.jgss.debug", "true");
      }

      // (KNOX-2001) Log a warning if the useSubjectCredsOnly restriction is "relaxed"
      String useSubjectCredsOnly = System.getProperty("javax.security.auth.useSubjectCredsOnly");
      if (useSubjectCredsOnly != null && !Boolean.parseBoolean(useSubjectCredsOnly)) {
        LOG.useSubjectCredsOnlyIsFalse();
      }

      final Registry<AuthSchemeProvider> authSchemeRegistry =
          RegistryBuilder.<AuthSchemeProvider>create().register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true)).build();

      return HttpClients.custom()
                        .setConnectionManager(connectionManager)
                        .setDefaultAuthSchemeRegistry(authSchemeRegistry)
                        .setDefaultCredentialsProvider(EMPTY_CREDENTIALS_PROVIDER)
                        .build();
    } else {
      AuthCache authCache = new BasicAuthCache();
      BasicScheme authScheme = new BasicScheme();
      authCache.put(host, authScheme);
      context = new BasicHttpContext();
      context.setAttribute(org.apache.http.client.protocol.HttpClientContext.AUTH_CACHE, authCache);

      CredentialsProvider credentialsProvider = null;
      if (clientContext.username() != null && clientContext.password() != null) {
        credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(new AuthScope(host.getHostName(), host.getPort()),
                                           new UsernamePasswordCredentials(clientContext.username(),
                                           clientContext.password()));
      }
      return HttpClients.custom()
                        .setConnectionManager(connectionManager)
                        .setDefaultCredentialsProvider(credentialsProvider)
                        .build();
    }

  }

  protected X509Certificate generateCertificateFromBytes(byte[] certBytes) throws CertificateException {
    CertificateFactory factory = CertificateFactory.getInstance("X.509");
    return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes));
  }

  private KeyStore getTrustStore(ClientContext clientContext) throws GeneralSecurityException {
    KeyStore ks;
    String truststorePass;

    // if a PEM file was provided create a keystore from that and use
    // it as the truststore
    String pem = clientContext.connection().endpointPublicCertPem();
    if (pem != null) {
      // strip delimiters
      if (pem.contains("BEGIN")) {
        pem = pem.substring(BEGIN_CERTIFICATE.length()-1,
            pem.indexOf(END_CERTIFICATE.substring(0, END_CERTIFICATE.length()-1)));
      }
      try {
        byte[] bytes = Base64.decodeBase64(pem);
        KeyStore keystore = KeyStore.getInstance("JKS");
        keystore.load(null);
        keystore.setCertificateEntry("knox-gateway", generateCertificateFromBytes(bytes));

        return keystore;
      } catch (IOException e) {
        LOG.unableToLoadProvidedPEMEncodedTrustedCert(e);
      }
    }

    discoverTruststoreDetails(clientContext);

    File file = new File(clientContext.connection().truststoreLocation());
    if (file.exists()) {
      truststorePass = clientContext.connection().truststorePass();
    } else {
      String truststore = System.getProperty("javax.net.ssl.trustStore");
      truststorePass = System.getProperty("javax.net.ssl.trustStorePassword", "changeit");
      if (truststore == null) {
        String truststoreDir = System.getProperty("java.home");
        truststore = truststoreDir + File.separator + "lib" + File.separator
                         + "security" + File.separator + "cacerts";
      }
      file = new File(truststore);
    }

    if (file.exists()) {
      try (InputStream is = Files.newInputStream(file.toPath())) {
        ks = KeyStore.getInstance("JKS");
        ks.load(is, truststorePass.toCharArray());
      } catch (KeyStoreException e) {
        throw new KnoxShellException("Unable to create keystore of expected type.", e);
      } catch (FileNotFoundException e) {
        throw new KnoxShellException("Unable to read truststore."
            + " Please import the gateway-identity certificate into the JVM"
            + " truststore or set the truststore location ENV variables.", e);
      } catch (NoSuchAlgorithmException e) {
        throw new KnoxShellException("Unable to load the truststore."
            + " Please import the gateway-identity certificate into the JVM"
            + " truststore or set the truststore location ENV variables.", e);
      } catch (CertificateException e) {
        throw new KnoxShellException("Certificate cannot be found in the truststore."
            + " Please import the gateway-identity certificate into the JVM"
            + " truststore or set the truststore location ENV variables.", e);
      } catch (IOException e) {
        throw new KnoxShellException("Unable to load truststore."
            + " May be related to password setting or truststore format.", e);
      }
    } else {
      throw new KnoxShellException("Unable to find a truststore for secure login."
                                       + "Please import the gateway-identity certificate into the JVM"
                                       + " truststore or set the truststore location ENV variables.");
    }

    return ks;
  }

  protected void discoverTruststoreDetails(ClientContext clientContext) {
    if (clientContext.connection().truststoreLocation() != null &&
        clientContext.connection().truststorePass() != null) {
      return;
    } else {
      final String truststoreLocation = ClientTrustStoreHelper.getClientTrustStoreFile().getAbsolutePath();
      final String truststorePass = ClientTrustStoreHelper.getClientTrustStoreFilePassword();
      clientContext.connection().withTruststore(truststoreLocation, truststorePass);
    }
  }

  public String base() {
    return base;
  }

  @SuppressForbidden
  public CloseableHttpResponse executeNow(HttpRequest request ) throws IOException {
    /* check for kerberos */
    if (isKerberos) {
      Subject subject = Subject.getSubject(AccessController.getContext());
      try {
        if (subject == null) {
          LOG.noSubjectAvailable();
          Configuration jaasConf;
          try {
            jaasConf = new JAASClientConfig(jaasConfigURL);
          } catch (Exception e) {
            LOG.failedToLoadJAASConfiguration(jaasConfigURL.toExternalForm());
            throw new KnoxShellException(e.toString(), e);
          }

          LoginContext lc = new LoginContext(JGSS_LOGIN_MOUDLE,
                                             null,
                                             new TextCallbackHandler(),
                                             jaasConf);
          lc.login();
          subject = lc.getSubject();
        }
        return Subject.doAs(subject,
            (PrivilegedAction<CloseableHttpResponse>) () -> {
              CloseableHttpResponse response;
              try {
                response = client.execute(host, request, context);
                if (response.getStatusLine().getStatusCode() < 400) {
                  return response;
                } else {
                  throw new ErrorResponse(
                      request.getRequestLine().getUri() + ": ", response);
                }
              } catch (final IOException e) {
                throw new KnoxShellException(e.toString(), e);
              }
            });

      } catch (final LoginException e) {
        throw new KnoxShellException(e.toString(), e);
      }
    } else {
      CloseableHttpResponse response = client.execute(host, request, context);
      if (response.getStatusLine().getStatusCode() < 400) {
        return response;
      } else {
        throw new ErrorResponse(request.getRequestLine().getUri() + ": ",
            response);
      }
    }
  }

  public <T> Future<T> executeLater( Callable<T> callable ) {
    return executor.submit( callable );
  }

  public void waitFor( Future<?>... futures ) throws ExecutionException, InterruptedException {
    if( futures != null ) {
      for( Future<?> future : futures ) {
        future.get();
      }
    }
  }

  public void waitFor( long timeout, TimeUnit units, Future<?>... futures ) throws ExecutionException, TimeoutException, InterruptedException {
    if( futures != null ) {
      timeout = TimeUnit.MILLISECONDS.convert( timeout, units );
      long start;
      for( Future<?> future : futures ) {
        start = System.currentTimeMillis();
        future.get( timeout, TimeUnit.MILLISECONDS );
        timeout -= ( System.currentTimeMillis() - start );
      }
    }
  }

  private void closeClient() throws IOException {
    if(client != null) {
      client.close();
    }
  }

  public void shutdown() throws InterruptedException, IOException {
    try {
      executor.shutdownNow();
    } finally {
      closeClient();
    }
  }

  public boolean shutdown( long timeout, TimeUnit unit ) throws InterruptedException, IOException {
    try{
      executor.shutdown();
      return executor.awaitTermination( timeout, unit );
    } finally {
      closeClient();
    }
  }

  @Override
  public void close() throws IOException {
    try {
      shutdown();
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw new KnoxShellException("Can not shutdown underlying resources", e);
    }
  }

  @Override
  public String toString() {
    return String.format(Locale.ROOT, "KnoxSession{base='%s'}", base);
  }

  /**
   * Persist provided Map to a file within the {user.home}/.knoxshell directory
   * @param <T> type of the list
   * @param fileName of persisted file
   * @param map to persist
   */
  public static <T> void persistToKnoxShell(String fileName, Map<String, List<T>> map) {
    String s = JsonUtils.renderAsJsonString(map);
    String home = System.getProperty("user.home");
    try {
      write(new File(home + File.separator + ".knoxshell" + File.separator + fileName), s);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  private static void write(File file, String s) throws IOException {
    synchronized(KnoxSession.class) {
      // Ensure the parent directory exists...
      // This will attempt to create all missing directories.  No failures will occur if the directories already exist.
      Files.createDirectories(file.toPath().getParent());
      try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.WRITE,
          StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
        channel.tryLock();
        FileUtils.write(file, s, StandardCharsets.UTF_8);
      } catch (OverlappingFileLockException e) {
        System.out.println("Unable to acquire write lock for: " + file.getAbsolutePath());
      }
    }
  }

  public static void persistSQLHistory(Map<String, List<String>> sqlHistories) {
    persistToKnoxShell(KNOXSQLHISTORIES_JSON, sqlHistories);
  }

  public static void persistDataSources(Map<String, List<KnoxDataSource>> datasources) {
    persistToKnoxShell(KNOXDATASOURCES_JSON, datasources);
  }

  /**
   * Load and return a map of datasource names to sql commands
   * from the {user.home}/.knoxshell/knoxsqlhistories.json file.
   * @return sqlHistory map
   * @throws IOException exception when loading sql history
   */
  public static Map<String, List<String>> loadSQLHistories() throws IOException {
    Map<String, List<String>> sqlHistories = null;
    String home = System.getProperty("user.home");

    File historyFile = new File(
        home + File.separator +
        ".knoxshell" + File.separator + KNOXSQLHISTORIES_JSON);
    if (historyFile.exists()) {
      String json = readFileToString(historyFile);
      sqlHistories = getMapOfStringArrayListsFromJsonString(json);
    }
    return sqlHistories;
  }

  private static String readFileToString(File file) throws IOException {
    String content = null;

    synchronized(KnoxSession.class) {
      try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ)) {
        channel.tryLock(0L, Long.MAX_VALUE, true);
        content = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
      } catch (OverlappingFileLockException e) {
        System.out.println("Unable to acquire write lock for: " + file.getAbsolutePath());
      }
    }

    return content;
  }

  /**
   * Load and return a map of datasource names to KnoxDataSource
   * objects from the {user.home}/.knoxshell/knoxdatasources.json file.
   * @return map of data sources
   * @throws IOException exception when loading data sources
   */
  public static Map<String, KnoxDataSource> loadDataSources() throws IOException {
    Map<String, KnoxDataSource> datasources = null;
    String home = System.getProperty("user.home");
    String json;

    File dsFile = new File(home + File.separator + ".knoxshell" + File.separator + KNOXDATASOURCES_JSON);
    if (dsFile.exists()) {
      json = readFileToString(dsFile);
      datasources = getMapOfDataSourcesFromJsonString(json);
    }

    return datasources;
  }

  public static Map<String, List<String>> getMapOfStringArrayListsFromJsonString(String json) throws IOException {
    Map<String, List<String>> obj;
    JsonFactory factory = new JsonFactory();
    ObjectMapper mapper = new ObjectMapper(factory);
    TypeReference<Map<String, List<String>>> typeRef = new TypeReference<Map<String, List<String>>>() {};
    obj = mapper.readValue(json, typeRef);
    return obj;
  }

  public static Map<String, KnoxDataSource> getMapOfDataSourcesFromJsonString(String json) throws IOException {
    Map<String, KnoxDataSource> obj;
    JsonFactory factory = new JsonFactory();
    ObjectMapper mapper = new ObjectMapper(factory);
    TypeReference<Map<String, KnoxDataSource>> typeRef = new TypeReference<Map<String, KnoxDataSource>>() {};
    obj = mapper.readValue(json, typeRef);
    return obj;
  }

  private static final class JAASClientConfig extends Configuration {
    private static final Configuration baseConfig = Configuration.getConfiguration();

    private Configuration configFile;

    JAASClientConfig(URL configFileURL) throws Exception {
      if (configFileURL != null) {
        this.configFile = ConfigurationFactory.create(configFileURL.toURI());
      }
    }

    @Override
    public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
      AppConfigurationEntry[] result = null;

      // Try the config file if it exists
      if (configFile != null) {
        result = configFile.getAppConfigurationEntry(name);
      }

      // If the entry isn't there, delegate to the base configuration
      if (result == null) {
        result = baseConfig.getAppConfigurationEntry(name);
      }

      return result;
    }
  }

  @SuppressWarnings("PMD.AvoidAccessibilityAlteration")
  private static class ConfigurationFactory {
    private static final Class implClazz;
    static {
      // Oracle and OpenJDK use the Sun implementation
      String implName = System.getProperty("java.vendor").contains("IBM") ?
                                "com.ibm.security.auth.login.ConfigFile" : "com.sun.security.auth.login.ConfigFile";

      LOG.usingJAASConfigurationFileImplementation(implName);
      Class clazz = null;
      try {
        clazz = Class.forName(implName, false, Thread.currentThread().getContextClassLoader());
      } catch (ClassNotFoundException e) {
        LOG.failedToLoadJAASConfigurationFileImplementation(implName, e.getLocalizedMessage());
      }

      implClazz = clazz;
    }

    static Configuration create(URI uri) {
      Configuration config = null;

      if (implClazz != null) {
        try {
          Constructor ctor = implClazz.getDeclaredConstructor(URI.class);
          config = (Configuration) ctor.newInstance(uri);
        } catch (Exception e) {
          LOG.failedToInstantiateJAASConfigurationFileImplementation(implClazz.getCanonicalName(),
                                                                     e.getLocalizedMessage());
        }
      } else {
        LOG.noJAASConfigurationFileImplementation();
      }

      return config;
    }
  }
}
