This is an automated email from the ASF dual-hosted git repository.

jchen21 pushed a commit to branch feature/GEODE-5861
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 8811734a852d0a77e47421060b4cdfb1dface8a5
Author: Darrel Schneider <dschnei...@pivotal.io>
AuthorDate: Fri Oct 12 16:50:42 2018 -0700

    WIP: Adding support for creating Hikari data source
    
    Co-authored-by: Darrel Schneider <dschnei...@pivotal.io>
    Co-authored-by: Jianxia Chen <jc...@pivotal.io>
---
 .../jdbc/internal/HikariJdbcDataSource.java        | 57 +++++++++++++-
 geode-core/build.gradle                            |  1 +
 .../internal/datasource/DataSourceFactory.java     | 22 ++++++
 .../internal/datasource/HikariJdbcDataSource.java  | 90 ++++++++++++++++++++++
 .../apache/geode/internal/jndi/JNDIInvoker.java    | 68 ++++++++++------
 .../cli/commands/CreateJndiBindingCommand.java     |  3 +-
 geode-core/src/test/resources/expected-pom.xml     |  6 ++
 7 files changed, 221 insertions(+), 26 deletions(-)

diff --git 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/HikariJdbcDataSource.java
 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/HikariJdbcDataSource.java
index 2aa3555..8e70e9c 100644
--- 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/HikariJdbcDataSource.java
+++ 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/HikariJdbcDataSource.java
@@ -14,14 +14,20 @@
  */
 package org.apache.geode.connectors.jdbc.internal;
 
+import java.io.PrintWriter;
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.logging.Logger;
+
+import javax.sql.DataSource;
 
 import com.zaxxer.hikari.HikariDataSource;
 
 import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
+import org.apache.geode.internal.datasource.ConfiguredDataSourceProperties;
 
-class HikariJdbcDataSource implements JdbcDataSource {
+public class HikariJdbcDataSource implements DataSource, JdbcDataSource {
 
   private final HikariDataSource delegate;
 
@@ -34,14 +40,63 @@ class HikariJdbcDataSource implements JdbcDataSource {
     this.delegate = ds;
   }
 
+  // TODO: set more config properties
+  public HikariJdbcDataSource(ConfiguredDataSourceProperties config) {
+    HikariDataSource ds = new HikariDataSource();
+    ds.setJdbcUrl(config.getURL());
+    ds.setUsername(config.getUser());
+    ds.setPassword(config.getPassword());
+//    ds.setDataSourceProperties(config.getConnectionProperties());
+    this.delegate = ds;
+  }
+
   @Override
   public Connection getConnection() throws SQLException {
     return this.delegate.getConnection();
   }
 
   @Override
+  public Connection getConnection(String username, String password) throws 
SQLException {
+    return this.delegate.getConnection(username, password);
+  }
+
+  @Override
   public void close() {
     this.delegate.close();
   }
 
+  @Override
+  public <T> T unwrap(Class<T> iface) throws SQLException {
+    return this.delegate.unwrap(iface);
+  }
+
+  @Override
+  public boolean isWrapperFor(Class<?> iface) throws SQLException {
+    return this.delegate.isWrapperFor(iface);
+  }
+
+  @Override
+  public PrintWriter getLogWriter() throws SQLException {
+    return this.delegate.getLogWriter();
+  }
+
+  @Override
+  public void setLogWriter(PrintWriter out) throws SQLException {
+    this.delegate.setLogWriter(out);
+  }
+
+  @Override
+  public void setLoginTimeout(int seconds) throws SQLException {
+    this.delegate.setLoginTimeout(seconds);
+  }
+
+  @Override
+  public int getLoginTimeout() throws SQLException {
+    return this.delegate.getLoginTimeout();
+  }
+
+  @Override
+  public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+    return this.delegate.getParentLogger();
+  }
 }
diff --git a/geode-core/build.gradle b/geode-core/build.gradle
index 3975797..ac3d9c2 100755
--- a/geode-core/build.gradle
+++ b/geode-core/build.gradle
@@ -45,6 +45,7 @@ dependencies {
   antlr 'antlr:antlr:' + project.'antlr.version'
 
   // External
+  compile group: 'com.zaxxer', name: 'HikariCP', version: 
project.'HikariCP.version'
   compileOnly files("${System.getProperty('java.home')}/../lib/tools.jar")
   compile 'com.github.stephenc.findbugs:findbugs-annotations:' + 
project.'stephenc-findbugs.version'
   compile 'org.jgroups:jgroups:' + project.'jgroups.version'
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/datasource/DataSourceFactory.java
 
b/geode-core/src/main/java/org/apache/geode/internal/datasource/DataSourceFactory.java
index 2143be5..e120cd5 100644
--- 
a/geode-core/src/main/java/org/apache/geode/internal/datasource/DataSourceFactory.java
+++ 
b/geode-core/src/main/java/org/apache/geode/internal/datasource/DataSourceFactory.java
@@ -53,6 +53,28 @@ public class DataSourceFactory {
   /** Creates a new instance of DataSourceFactory */
   public DataSourceFactory() {}
 
+  public static DataSource getHikariDataSource(Map configMap)  throws 
DataSourceCreateException {
+    ConfiguredDataSourceProperties configs = 
createDataSourceProperties(configMap);
+    if (configs.getURL() == null) {
+      logger.error("DataSourceFactory::getHikariDataSource:URL String to 
Database is null");
+      throw new DataSourceCreateException(
+          "DataSourceFactory::getHikariDataSource:URL String to Database is 
null");
+    }
+    try {
+      return new HikariJdbcDataSource(configs);
+    } catch (Exception ex) {
+      logger.error(String.format(
+          "DataSourceFactory::getHikariDataSource:Exception while creating 
GemfireBasicDataSource.Exception String=%s",
+          ex.getLocalizedMessage()),
+          ex);
+      throw new DataSourceCreateException(
+          String.format(
+              "DataSourceFactory::getHikariDataSource:Exception while creating 
GemfireBasicDataSource.Exception String=%s",
+              ex.getLocalizedMessage()),
+          ex);
+    }
+  }
+
   /**
    * This function returns the Basic datasource without any pooling.
    *
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/datasource/HikariJdbcDataSource.java
 
b/geode-core/src/main/java/org/apache/geode/internal/datasource/HikariJdbcDataSource.java
new file mode 100644
index 0000000..9a37945
--- /dev/null
+++ 
b/geode-core/src/main/java/org/apache/geode/internal/datasource/HikariJdbcDataSource.java
@@ -0,0 +1,90 @@
+/*
+ * 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;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.logging.Logger;
+
+import javax.sql.DataSource;
+
+import com.zaxxer.hikari.HikariDataSource;
+
+class HikariJdbcDataSource implements DataSource, AutoCloseable {
+
+  private final HikariDataSource delegate;
+
+  // TODO: set more config properties
+  HikariJdbcDataSource(ConfiguredDataSourceProperties config) {
+    HikariDataSource ds = new HikariDataSource();
+    ds.setJdbcUrl(config.getURL());
+    ds.setUsername(config.getUser());
+    ds.setPassword(config.getPassword());
+//    ds.setDataSourceProperties(config.getConnectionProperties());
+    this.delegate = ds;
+  }
+
+  @Override
+  public Connection getConnection() throws SQLException {
+    return this.delegate.getConnection();
+  }
+
+  @Override
+  public Connection getConnection(String username, String password) throws 
SQLException {
+    return this.delegate.getConnection(username, password);
+  }
+
+  @Override
+  public void close() {
+    this.delegate.close();
+  }
+
+  @Override
+  public <T> T unwrap(Class<T> iface) throws SQLException {
+    return this.delegate.unwrap(iface);
+  }
+
+  @Override
+  public boolean isWrapperFor(Class<?> iface) throws SQLException {
+    return this.delegate.isWrapperFor(iface);
+  }
+
+  @Override
+  public PrintWriter getLogWriter() throws SQLException {
+    return this.delegate.getLogWriter();
+  }
+
+  @Override
+  public void setLogWriter(PrintWriter out) throws SQLException {
+    this.delegate.setLogWriter(out);
+  }
+
+  @Override
+  public void setLoginTimeout(int seconds) throws SQLException {
+    this.delegate.setLoginTimeout(seconds);
+  }
+
+  @Override
+  public int getLoginTimeout() throws SQLException {
+    return this.delegate.getLoginTimeout();
+  }
+
+  @Override
+  public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+    return this.delegate.getParentLogger();
+  }
+}
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/jndi/JNDIInvoker.java 
b/geode-core/src/main/java/org/apache/geode/internal/jndi/JNDIInvoker.java
index 8206cc8..f325963 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/jndi/JNDIInvoker.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/jndi/JNDIInvoker.java
@@ -21,6 +21,8 @@ import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import javax.naming.Binding;
 import javax.naming.Context;
@@ -29,9 +31,13 @@ import javax.naming.NameNotFoundException;
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
 import javax.naming.NoInitialContextException;
+import javax.sql.DataSource;
 import javax.transaction.SystemException;
 import javax.transaction.TransactionManager;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
 import org.apache.geode.LogWriter;
 import org.apache.geode.distributed.DistributedSystem;
 import org.apache.geode.distributed.internal.DistributionConfig;
@@ -44,6 +50,7 @@ import org.apache.geode.internal.datasource.DataSourceFactory;
 import org.apache.geode.internal.jta.TransactionManagerImpl;
 import org.apache.geode.internal.jta.TransactionUtils;
 import org.apache.geode.internal.jta.UserTransactionImpl;
+import org.apache.geode.internal.logging.LogService;
 
 /**
  * <p>
@@ -66,6 +73,8 @@ import org.apache.geode.internal.jta.UserTransactionImpl;
  */
 public class JNDIInvoker {
 
+  private static final Logger logger = LogService.getLogger();
+
   // private static boolean DEBUG = false;
   /**
    * JNDI Context, this may refer to GemFire JNDI Context or external Context, 
in case the external
@@ -103,7 +112,8 @@ public class JNDIInvoker {
    * List of DataSource bound to the context, used for cleaning gracefully 
closing datasource and
    * associated threads.
    */
-  private static List dataSourceList = new ArrayList();
+//  private static List dataSourceList = new ArrayList();
+  private static final ConcurrentMap<String, DataSource> dataSourceMap = new 
ConcurrentHashMap<>();
 
   /**
    * If this system property is set to true, GemFire will not try to lookup 
for an existing JTA
@@ -208,16 +218,27 @@ public class JNDIInvoker {
         // ok to ignore, rebind will be tried later
       }
     }
-    int len = dataSourceList.size();
-    for (int i = 0; i < len; i++) {
-      if (dataSourceList.get(i) instanceof AbstractDataSource)
-        ((AbstractDataSource) dataSourceList.get(i)).clearUp();
-      else if (dataSourceList.get(i) instanceof 
ClientConnectionFactoryWrapper) {
-        ((ClientConnectionFactoryWrapper) dataSourceList.get(i)).clearUp();
+    dataSourceMap.values().stream().forEach(JNDIInvoker::closeDataSource);
+    dataSourceMap.clear();
+    IGNORE_JTA = Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + 
"ignoreJTA");
+  }
+
+  private static void closeDataSource(DataSource dataSource) {
+    if (dataSource instanceof AutoCloseable) {
+      try {
+        ((AutoCloseable) dataSource).close();
+      } catch (Exception e) {
+        if (logger.isDebugEnabled()) {
+          logger.debug("Exception closing DataSource", e);
+        }
       }
     }
-    dataSourceList.clear();
-    IGNORE_JTA = Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + 
"ignoreJTA");
+    else if (dataSource instanceof AbstractDataSource) {
+      ((AbstractDataSource) dataSource).clearUp();
+    }
+    else if (dataSource instanceof ClientConnectionFactoryWrapper) {
+      ((ClientConnectionFactoryWrapper) dataSource).clearUp();
+    }
   }
 
   /*
@@ -321,31 +342,37 @@ public class JNDIInvoker {
     String value = (String) map.get("type");
     String jndiName = "";
     LogWriter writer = TransactionUtils.getLogWriter();
-    Object ds = null;
+    DataSource ds = null;
     try {
       jndiName = (String) map.get("jndi-name");
       if (value.equals("PooledDataSource")) {
         ds = DataSourceFactory.getPooledDataSource(map, props);
         ctx.rebind("java:/" + jndiName, ds);
-        dataSourceList.add(ds);
+        dataSourceMap.put(jndiName, ds);
         if (writer.fineEnabled())
           writer.fine("Bound java:/" + jndiName + " to Context");
       } else if (value.equals("XAPooledDataSource")) {
         ds = DataSourceFactory.getTranxDataSource(map, props);
         ctx.rebind("java:/" + jndiName, ds);
-        dataSourceList.add(ds);
+        dataSourceMap.put(jndiName, ds);
         if (writer.fineEnabled())
           writer.fine("Bound java:/" + jndiName + " to Context");
       } else if (value.equals("SimpleDataSource")) {
         ds = DataSourceFactory.getSimpleDataSource(map);
         ctx.rebind("java:/" + jndiName, ds);
-        dataSourceList.add(ds);
+        dataSourceMap.put(jndiName, ds);
+        if (writer.fineEnabled())
+          writer.fine("Bound java:/" + jndiName + " to Context");
+      } else if (value.equals("HikariDataSource")) {
+        ds = DataSourceFactory.getHikariDataSource(map);
+        ctx.rebind("java:/" + jndiName, ds);
+        dataSourceMap.put(jndiName, ds);
         if (writer.fineEnabled())
           writer.fine("Bound java:/" + jndiName + " to Context");
       } else if (value.equals("ManagedDataSource")) {
         ClientConnectionFactoryWrapper ds1 = 
DataSourceFactory.getManagedDataSource(map, props);
         ctx.rebind("java:/" + jndiName, ds1.getClientConnFactory());
-        dataSourceList.add(ds1);
+        dataSourceMap.put(jndiName, ds);
         if (writer.fineEnabled())
           writer.fine("Bound java:/" + jndiName + " to Context");
       } else {
@@ -370,15 +397,8 @@ public class JNDIInvoker {
 
   public static void unMapDatasource(String jndiName) throws NamingException {
     ctx.unbind("java:/" + jndiName);
-    for (Iterator it = dataSourceList.iterator(); it.hasNext();) {
-      Object obj = it.next();
-      if (obj instanceof AbstractDataSource) {
-        ((AbstractDataSource) obj).clearUp();
-      } else if (obj instanceof ClientConnectionFactoryWrapper) {
-        ((ClientConnectionFactoryWrapper) obj).clearUp();
-      }
-      it.remove();
-    }
+    DataSource removedDataSource = dataSourceMap.remove(jndiName);
+    closeDataSource(removedDataSource);
   }
 
   /**
@@ -398,7 +418,7 @@ public class JNDIInvoker {
   }
 
   public static int getNoOfAvailableDataSources() {
-    return dataSourceList.size();
+    return dataSourceMap.size();
   }
 
   public static Map<String, String> getBindingNamesRecursively(Context ctx) 
throws Exception {
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateJndiBindingCommand.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateJndiBindingCommand.java
index e034aef..bebb226 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateJndiBindingCommand.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateJndiBindingCommand.java
@@ -182,7 +182,8 @@ public class CreateJndiBindingCommand extends 
SingleGfshCommand {
     MANAGED("ManagedDataSource"),
     SIMPLE("SimpleDataSource"),
     POOLED("PooledDataSource"),
-    XAPOOLED("XAPooledDataSource");
+    XAPOOLED("XAPooledDataSource"),
+    HIKARI("HikariDataSource");
 
     private final String type;
 
diff --git a/geode-core/src/test/resources/expected-pom.xml 
b/geode-core/src/test/resources/expected-pom.xml
index 0ff3525..1428d4a 100644
--- a/geode-core/src/test/resources/expected-pom.xml
+++ b/geode-core/src/test/resources/expected-pom.xml
@@ -36,6 +36,12 @@
   </scm>
   <dependencies>
     <dependency>
+      <groupId>com.zaxxer</groupId>
+      <artifactId>HikariCP</artifactId>
+      <version>3.2.0</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
       <groupId>com.github.stephenc.findbugs</groupId>
       <artifactId>findbugs-annotations</artifactId>
       <version>1.3.9-1</version>

Reply via email to