/*
 * 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.datasource;

/**
 * This class models a datasource factory.The datasource factory has funtions to create 3 types of
 * datasources. 1) Basic datasource without any connection pooling. 2) Datasource with pooled
 * connections. 3) Datasource with pooled connection and transaction capabilities.
 *
 * The invokeAllMethods was setting only some specific properties Modified the code so that any key
 * value mentioned in <property>tag is attempted for setting. If the property has a key as
 * serverName , then the setter method is invoked with the name setServerName & the value present in
 * value attribute is passed Made the Exception handling robust
 *
 * Changed invokeAllMethods wrt the change in cache.xml for vendor specific properties.
 *
 */
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.resource.spi.ConnectionManager;
import javax.resource.spi.ManagedConnectionFactory;
import javax.sql.DataSource;
import javax.sql.XADataSource;

import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.internal.MutableForTesting;
import org.apache.geode.datasource.PooledDataSourceFactory;
import org.apache.geode.internal.ClassPathLoader;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.util.PasswordUtil;

public class DataSourceFactory {

  private static final Logger logger = LogService.getLogger();

  private static final String DEFAULT_CONNECTION_POOL_DS_CLASS =
      "org.apache.geode.connectors.jdbc.JdbcPooledDataSourceFactory";

  private static final String POOL_PREFIX = "pool.";

  /** Creates a new instance of DataSourceFactory */
  public DataSourceFactory() {}

  /**
   * This function returns the Basic datasource without any pooling.
   *
   * @param configMap a map containing configurations required for datasource.
   * @return ??
   */
  public DataSource getSimpleDataSource(Map configMap) throws DataSourceCreateException {
    ConfiguredDataSourceProperties configs = createDataSourceProperties(configMap);
    if (configs.getURL() == null) {
      logger.error("DataSourceFactory::getSimpleDataSource:URL String to Database is null");
      throw new DataSourceCreateException(
          "DataSourceFactory::getSimpleDataSource:URL String to Database is null");
    }
    try {
      return new GemFireBasicDataSource(configs);
    } catch (Exception ex) {
      logger.error(String.format(
          "DataSourceFactory::getSimpleDataSource:Exception while creating GemfireBasicDataSource.Exception String=%s",
          ex.getLocalizedMessage()),
          ex);
      throw new DataSourceCreateException(
          String.format(
              "DataSourceFactory::getSimpleDataSource:Exception while creating GemfireBasicDataSource.Exception String=%s",
              ex.getLocalizedMessage()),
          ex);
    }
  }

  /**
   * This function creates a data source from the ManagedConnectionFactory class using the
   * connectionManager.
   *
   * @return javax.sql.DataSource
   */
  public ClientConnectionFactoryWrapper getManagedDataSource(Map configMap,
      List<ConfigProperty> props) throws DataSourceCreateException {
    Object cf = null;
    ManagedConnectionFactory mcf = null;
    ConfiguredDataSourceProperties configs = createDataSourceProperties(configMap);
    if (configs.getMCFClass() == null) {
      logger.error(
          "DataSourceFactory::getManagedDataSource:Managed Connection factory class is not available");
      throw new DataSourceCreateException(
          "DataSourceFactory::getManagedDataSource:Managed Connection factory class is not available");
    } else {
      try {
        Class cl = ClassPathLoader.getLatest().forName(configs.getMCFClass());
        mcf = (ManagedConnectionFactory) cl.newInstance();
        invokeAllMethods(cl, mcf, props);
      } catch (Exception ex) {
        logger.error(String.format(
            "DataSourceFactory::getManagedDataSource: Exception in creating managed connection factory. Exception string, %s",
            ex));
        throw new DataSourceCreateException(
            String.format(
                "DataSourceFactory::getManagedDataSource: Exception in creating managed connection factory. Exception string, %s",
                ex));
      }
    }
    // Initialize the managed connection factory class
    // Instantiate a connection manager with the managed-conn-facory-class
    // and generate a connection pool.
    Object cm = null;
    if (configs.getMCFClass().equals("org.apache.persistence.connection.internal.ConnFactory")) {
      cm = new FacetsJCAConnectionManagerImpl(mcf, configs);
    } else {
      cm = new JCAConnectionManagerImpl(mcf, configs);
    }
    try {
      cf = mcf.createConnectionFactory((ConnectionManager) cm);
    } catch (Exception ex) {
      logger.error(
          "DataSourceFactory::getManagedDataSource: Exception in creating managed connection factory. Exception string, %s",
          ex.toString());
      throw new DataSourceCreateException(
          String.format(
              "DataSourceFactory::getManagedDataSource: Exception in creating managed connection factory. Exception string, %s",
              ex));
    }
    return new ClientConnectionFactoryWrapper(cf, cm);
  }

  /**
   * This function returns the datasource with connection pooling.
   */
  public DataSource getPooledDataSource(Map configMap, List<ConfigProperty> props)
      throws DataSourceCreateException {
    ConfiguredDataSourceProperties configs = createDataSourceProperties(configMap);
    String connpoolClassName = configs.getConnectionPoolDSClass();
    if (connpoolClassName == null) {
      connpoolClassName = DEFAULT_CONNECTION_POOL_DS_CLASS;
    }
    try {
      Properties poolProperties = createPoolProperties(configMap, props);
      Properties dataSourceProperties = createDataSourceProperties(props);
      Class<?> cl = ClassPathLoader.getLatest().forName(connpoolClassName);
      PooledDataSourceFactory factory = (PooledDataSourceFactory) cl.newInstance();
      return factory.createDataSource(poolProperties, dataSourceProperties);
    } catch (Exception ex) {
      String exception =
          String.format(
              "DataSourceFactory::getPooledDataSource:Exception creating ConnectionPoolDataSource.Exception string=%s",
              new Object[] {ex});
      logger.error(String.format(
          "DataSourceFactory::getPooledDataSource:Exception creating ConnectionPoolDataSource.Exception string=%s",
          ex),
          ex);
      throw new DataSourceCreateException(exception, ex);
    }
  }

  static Properties createPoolProperties(Map<String, String> configMap,
      List<ConfigProperty> props) {
    Properties result = new Properties();
    if (props != null) {
      for (ConfigProperty prop : props) {
        if (prop.getName().toLowerCase().startsWith(POOL_PREFIX)) {
          String poolName = prop.getName().substring(POOL_PREFIX.length());
          result.setProperty(poolName, prop.getValue());
        }
      }
    }
    if (configMap != null) {
      for (Map.Entry<String, String> entry : configMap.entrySet()) {
        if (entry.getValue() == null || entry.getValue().equals("")) {
          continue;
        }
        if (entry.getKey().equals("type")) {
          continue;
        }
        if (entry.getKey().equals("jdbc-driver-class")) {
          continue;
        }
        if (entry.getKey().equals("jndi-name")) {
          continue;
        }
        if (entry.getKey().equals("transaction-type")) {
          continue;
        }
        if (entry.getKey().equals("conn-pooled-datasource-class")) {
          continue;
        }
        if (entry.getKey().equals("managed-conn-factory-class")) {
          continue;
        }
        if (entry.getKey().equals("xa-datasource-class")) {
          continue;
        }
        result.setProperty(entry.getKey(), entry.getValue());
      }
    }
    return result;
  }

  static Properties createDataSourceProperties(List<ConfigProperty> props) {
    Properties result = new Properties();
    if (props != null) {
      for (ConfigProperty prop : props) {
        if (prop.getName().toLowerCase().startsWith(POOL_PREFIX)) {
          continue;
        }
        result.setProperty(prop.getName(), prop.getValue());
      }
    }
    return result;
  }


  /**
   * This function returns the datasource with connection pooling and transaction participation
   * capabilities.
   *
   * @param configMap a map containing configurations required for datasource.
   * @return ???
   */
  public DataSource getTranxDataSource(Map configMap, List<ConfigProperty> props)
      throws DataSourceCreateException {
    ConfiguredDataSourceProperties configs = createDataSourceProperties(configMap);
    String xaClassName = configs.getXADSClass();
    if (xaClassName == null) {
      logger.error(
          "DataSourceFactory::getTranxDataSource:XADataSource class name for the ResourceManager is not available");
      throw new DataSourceCreateException(
          "DataSourceFactory::getTranxDataSource:XADataSource class name for the ResourceManager is not available");
    }
    if (TEST_CONNECTION_HOST != null) {
      props.add(new ConfigProperty("serverName", TEST_CONNECTION_HOST, "java.lang.String"));
    }
    if (TEST_CONNECTION_PORT != null) {
      props.add(new ConfigProperty("portNumber", TEST_CONNECTION_PORT, "int"));
    }
    try {
      Class cl = ClassPathLoader.getLatest().forName(xaClassName);
      Object Obj = cl.newInstance();
      invokeAllMethods(cl, Obj, props);
      return new GemFireTransactionDataSource((XADataSource) Obj, configs);
    } catch (Exception ex) {
      String exception =
          String.format(
              "DataSourceFactory::getTranxDataSource:Exception in creating GemFireTransactionDataSource. Exception string=%s",
              new Object[] {ex});
      logger.error(String.format(
          "DataSourceFactory::getTranxDataSource:Exception in creating GemFireTransactionDataSource. Exception string=%s",
          ex),
          ex);
      throw new DataSourceCreateException(exception, ex);
    }
  }

  /**
   * Creates ConfiguredDataSourceProperties from map.
   *
   * @param configMap a map containing configurations required for datasource.
   */
  private ConfiguredDataSourceProperties createDataSourceProperties(Map configMap) {
    ConfiguredDataSourceProperties configs = new ConfiguredDataSourceProperties();
    Iterator entries = configMap.entrySet().iterator();
    while (entries.hasNext()) {
      Map.Entry entry = (Map.Entry) entries.next();
      String name = (String) entry.getKey();
      final Object obj = entry.getValue();
      if (name.equals("connection-url"))
        configs.setURL((String) obj);
      else if (name.equals("user-name"))
        configs.setUser((String) obj);
      else if (name.equals("password"))
        configs.setPassword(PasswordUtil.decrypt((String) obj));
      else if (name.equals("jdbc-driver-class"))
        configs.setJDBCDriver((String) obj);
      else if (name.equals("init-pool-size"))
        configs.setInitialPoolSize(Integer.parseInt((String) (obj == null
            ? String.valueOf(DataSourceResources.CONNECTION_POOL_DEFAULT_INIT_LIMIT) : obj)));
      else if (name.equals("max-pool-size"))
        configs.setMaxPoolSize(Integer.parseInt((String) (obj == null
            ? String.valueOf(DataSourceResources.CONNECTION_POOL_DEFAULT_MAX_LIMIT) : obj)));
      else if (name.equals("idle-timeout-seconds"))
        configs.setConnectionExpirationTime(Integer.parseInt((String) (obj == null
            ? String.valueOf(DataSourceResources.CONNECTION_POOL_DEFAULT_EXPIRATION_TIME) : obj)));
      else if (name.equals("blocking-timeout-seconds"))
        configs.setConnectionTimeOut(Integer.parseInt((String) (obj == null
            ? String.valueOf(DataSourceResources.CONNECTION_POOL_DEFAULT_ACTIVE_TIME_OUT) : obj)));
      else if (name.equals("login-timeout-seconds"))
        configs.setLoginTimeOut(Integer.parseInt((String) (obj == null
            ? String.valueOf(DataSourceResources.CONNECTION_POOL_DEFAULT_CLIENT_TIME_OUT) : obj)));
      else if (name.equals("conn-pooled-datasource-class"))
        configs.setConnectionPoolDSClass((String) obj);
      else if (name.equals("xa-datasource-class"))
        configs.setXADSClass((String) obj);
      else if (name.equals("managed-conn-factory-class"))
        configs.setMCFClass((String) obj);
      else if (name.equals("transaction-type"))
        configs.setTransactionType((String) obj);
    }

    /*
     * Test hook for replacing URL
     */
    if (TEST_CONNECTION_URL != null) {
      configs.setURL((String) TEST_CONNECTION_URL);
    }
    return configs;
  }

  /*
   * Test hook for replacing URL
   */
  @MutableForTesting
  private static String TEST_CONNECTION_URL = null;
  @MutableForTesting
  private static String TEST_CONNECTION_HOST = null;
  @MutableForTesting
  private static String TEST_CONNECTION_PORT = null;

  /*
   * Test hook for replacing URL
   */
  public static void setTestConnectionUrl(String url) {
    TEST_CONNECTION_URL = url;
  }

  /*
   * Test hook for replacing Host
   */
  public static void setTestConnectionHost(String host) {
    TEST_CONNECTION_HOST = host;
  }

  /*
   * Test hook for replacing Port
   */
  public static void setTestConnectionPort(String port) {
    TEST_CONNECTION_PORT = port;
  }


  /**
   *
   * dynamically invokes all the methods in the specified object.
   *
   * Asif: Rewrote the function as the number of properties to be set for a given datasource is
   * dynamic
   *
   * Rohit: Rewrote to accomodate the change in cache.xml. property tag is now replaced by
   * config-property for vendor specific data to get the Class name dynamically. CLass name is
   * specified in config-property-type tag and is stored in ConfigProperty Data Object after parsing
   * cache.xml.
   *
   * @param c class of the object
   * @param cpdsObj The object
   */
  private void invokeAllMethods(Class c, Object cpdsObj, List props)
      throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    String key = null;
    String value = null;
    String type = null;
    String methodName = null;
    Method m = null;
    for (Iterator it = props.iterator(); it.hasNext();) {
      ConfigProperty cp = (ConfigProperty) it.next();
      key = cp.getName();
      value = cp.getValue();
      type = cp.getType();
      if (key.indexOf("password") != -1) {
        value = PasswordUtil.decrypt(String.valueOf(value));
      }
      methodName = new StringBuffer("set").append(Character.toUpperCase(key.charAt(0)))
          .append(key.length() > 1 ? key.substring(1) : "").toString();
      try {
        Class cl = null;
        Class realClass = null;
        if ("int".equals(type)) {
          cl = int.class;
          realClass = java.lang.Integer.class;
        } else {
          cl = ClassPathLoader.getLatest().forName(type);
          realClass = cl;
        }
        Constructor cr = realClass.getConstructor(new Class[] {java.lang.String.class});
        Object ob = cr.newInstance(new Object[] {value});
        m = c.getMethod(methodName, new Class[] {cl});
        m.invoke(cpdsObj, new Object[] {ob});
      } catch (ClassNotFoundException ex) {
        String exception =
            String.format(
                "DataSourceFactory::invokeAllMethods: Exception in creating Class with the given config-property-type classname. Exception string=%s",
                ex.toString());
        if (logger.isDebugEnabled()) {
          logger.debug(exception, ex);
        }
      } catch (NoSuchMethodException ex) {
        String exception =
            String.format(
                "DataSourceFactory::invokeAllMethods: Exception in creating method using config-property-name property. Exception string=%s",
                ex.toString());
        if (logger.isDebugEnabled()) {
          logger.debug(exception, ex);
        }
      } catch (InstantiationException ex) {
        String exception =
            String.format(
                "DataSourceFactory::invokeAllMethods: Exception in creating instance of the class using the constructor with a String parameter. Exception string=%s",
                ex.toString());
        if (logger.isDebugEnabled()) {
          logger.debug(exception, ex);
        }
      }
    }
  }
}
