From f71e711c0cc272d1a56b19ac9be109d7c67d134d Mon Sep 17 00:00:00 2001 From: Bela Ban Date: Thu, 2 May 2024 17:34:49 +0200 Subject: [PATCH] - Added datasource_injecter_class (https://issues.redhat.com/browse/JGRP-2799) - Added getters and setters for attributes/properties in JDBC_PING --- src/org/jgroups/protocols/JDBC_PING.java | 121 ++++++++++++++--------- 1 file changed, 72 insertions(+), 49 deletions(-) diff --git a/src/org/jgroups/protocols/JDBC_PING.java b/src/org/jgroups/protocols/JDBC_PING.java index 313de9b572..41c23bed6f 100644 --- a/src/org/jgroups/protocols/JDBC_PING.java +++ b/src/org/jgroups/protocols/JDBC_PING.java @@ -11,6 +11,7 @@ import javax.sql.DataSource; import java.sql.*; import java.util.List; +import java.util.function.Function; /** *

Discovery protocol using a JDBC connection to a shared database. @@ -84,6 +85,10 @@ public class JDBC_PING extends FILE_PING { "properties must be empty.") protected String datasource_jndi_name; + @Property(description="The fully qualified name of a class which implements a Function. " + + "If not null, this has precedence over datasource_jndi_name.") + protected String datasource_injecter_class; + /* --------------------------------------------- Fields ------------------------------------------------------ */ protected DataSource dataSource; @@ -93,20 +98,52 @@ public class JDBC_PING extends FILE_PING { ; // do *not* create root file system (don't remove !) } - public JDBC_PING setDataSource(DataSource dataSource) { - this.dataSource = dataSource; return this; - } + public JDBC_PING setDataSource(DataSource ds) {this.dataSource=ds; return this;} + public DataSource getDataSource() {return dataSource;} + public String getConnectionUrl() {return connection_url;} + public JDBC_PING setConnectionUrl(String c) {this.connection_url=c; return this;} + public String getConnectionUsername() {return connection_username;} + public JDBC_PING setConnectionUsername(String c) {this.connection_username=c; return this;} + public String getConnectionPassword() {return connection_password;} + public JDBC_PING setConnectionPassword(String c) {this.connection_password=c; return this;} + public String getConnectionDriver() {return connection_driver;} + public JDBC_PING setConnectionDriver(String c) {this.connection_driver=c; return this;} + public String getInitializeSql() {return initialize_sql;} + public JDBC_PING setInitializeSql(String i) {this.initialize_sql=i; return this;} + public String getInsertSingleSql() {return insert_single_sql;} + public JDBC_PING setInsertSingleSql(String i) {this.insert_single_sql=i; return this;} + public String getDeleteSingleSql() {return delete_single_sql;} + public JDBC_PING setDeleteSingleSql(String d) {this.delete_single_sql=d; return this;} + public String getClearSql() {return clear_sql;} + public JDBC_PING setClearSql(String c) {this.clear_sql=c; return this;} + public String getSelectAllPingdataSql() {return select_all_pingdata_sql;} + public JDBC_PING setSelectAllPingdataSql(String s) {this.select_all_pingdata_sql=s; return this;} + public String getContainsSql() {return contains_sql;} + public JDBC_PING setContainsSql(String c) {this.contains_sql=c; return this;} + public String getDatasourceJndiName() {return datasource_jndi_name;} + public JDBC_PING setDatasourceJndiName(String d) {this.datasource_jndi_name=d; return this;} + public String getDatasourceInjecterClass() {return datasource_injecter_class;} + public JDBC_PING setDatasourceInjecterClass(String d) {this.datasource_injecter_class=d; return this;} + @Override public void init() throws Exception { super.init(); verifyConfigurationParameters(); // If dataSource is already set, skip loading driver or JNDI lookup - if (dataSource == null) { - if (stringIsEmpty(datasource_jndi_name)) { - loadDriver(); - } else { - dataSource = getDataSourceFromJNDI(datasource_jndi_name.trim()); + if(dataSource == null) { + if(datasource_injecter_class != null) { + dataSource=injectDataSource(datasource_injecter_class); + if(dataSource == null) { + String m=String.format("datasource_injecter_class %s created null datasource", datasource_injecter_class); + throw new IllegalArgumentException(m); + } + } + else { + if(datasource_jndi_name != null) + dataSource=getDataSourceFromJNDI(datasource_jndi_name.trim()); + else + loadDriver(); } } attemptSchemaInitialization(); @@ -248,8 +285,8 @@ protected void readAll(Connection connection, List

members, String clus protected void attemptSchemaInitialization() { - if(stringIsEmpty(initialize_sql)) { - log.debug("Table creation step skipped: initialize_sql property is missing"); + if(initialize_sql == null) { + log.debug("Table creation step skipped: initialize_sql attribute is missing"); return; } Connection connection=getConnection(); @@ -272,17 +309,24 @@ protected void attemptSchemaInitialization() { } protected void loadDriver() { - if (stringIsEmpty(connection_driver)) - return; - log.debug("Registering JDBC Driver named '%s'", connection_driver); + assertNonNull("connection_driver", connection_driver); + log.debug("Registering JDBC driver %s", connection_driver); try { Util.loadClass(connection_driver, this.getClass().getClassLoader()); - } catch (ClassNotFoundException e) { - throw new IllegalArgumentException("JDBC Driver required for JDBC_PING " - + " protocol could not be loaded: '" + connection_driver + "'"); } + catch (ClassNotFoundException e) { + throw new IllegalArgumentException(String.format("JDBC driver could not be loaded: '%s'", connection_driver)); + } + } + + protected DataSource injectDataSource(String ds_class) throws Exception { + Class cl=Util.loadClass(ds_class, Thread.currentThread().getContextClassLoader()); + Object obj=cl.getConstructor().newInstance(); + Function fun=(Function)obj; + return fun.apply(this); } + // todo: check if connections should be cached (connection pool?) protected Connection getConnection() { if (dataSource == null) { Connection connection; @@ -412,43 +456,22 @@ protected DataSource getDataSourceFromJNDI(String name) { } protected void verifyConfigurationParameters() { - // Skip if datasource is already provided via integration code (e.g. WildFly) - if (dataSource == null) { - if (stringIsEmpty(this.connection_url) || - stringIsEmpty(this.connection_driver) || - stringIsEmpty(this.connection_username)) { - if (stringIsEmpty(this.datasource_jndi_name)) { - throw new IllegalArgumentException("Either the 4 configuration properties starting with 'connection_' or the datasource_jndi_name must be set"); - } - } - if (stringNotEmpty(this.connection_url) || - stringNotEmpty(this.connection_driver) || - stringNotEmpty(this.connection_username)) { - if (stringNotEmpty(this.datasource_jndi_name)) { - throw new IllegalArgumentException("When using the 'datasource_jndi_name' configuration property, all properties starting with 'connection_' must not be set"); - } - } - } - if (stringIsEmpty(this.insert_single_sql)) { - throw new IllegalArgumentException("The insert_single_sql configuration property is mandatory"); - } - if (stringIsEmpty(this.delete_single_sql)) { - throw new IllegalArgumentException("The delete_single_sql configuration property is mandatory"); - } - if (stringIsEmpty(this.select_all_pingdata_sql)) { - throw new IllegalArgumentException("The select_all_pingdata_sql configuration property is mandatory"); - } - } - - private static boolean stringIsEmpty(final String value) { - return value == null || value.trim().isEmpty(); + // initialize_sql is skipped as the table could be created external to JDBC_PING + assertNonNull("insert_single_sql", insert_single_sql, + "clear_sql", clear_sql, + "delete_single_sql", delete_single_sql, + "select_all_pingdata_sql", select_all_pingdata_sql, + "contains_sql", contains_sql); } - private static boolean stringNotEmpty(final String value) { - return !stringIsEmpty(value); + protected static void assertNonNull(String... strings) { + for(int i=0; i < strings.length; i+=2) { + String attr=strings[i], val=strings[i+1]; + if(val == null) + throw new IllegalArgumentException(String.format("%s must not be null", attr)); + } } - public static void main(String[] args) throws ClassNotFoundException { String driver="org.hsqldb.jdbcDriver"; String user="SA";