Skip to content

Commit

Permalink
- Added datasource_injecter_class (https://issues.redhat.com/browse/J…
Browse files Browse the repository at this point in the history
…GRP-2799)

- Added getters and setters for attributes/properties in JDBC_PING
  • Loading branch information
belaban committed May 3, 2024
1 parent 15d6eeb commit 56e4ad8
Showing 1 changed file with 72 additions and 49 deletions.
121 changes: 72 additions & 49 deletions src/org/jgroups/protocols/JDBC_PING.java
Expand Up @@ -10,6 +10,7 @@
import javax.sql.DataSource;
import java.sql.*;
import java.util.List;
import java.util.function.Function;

/**
* <p>Discovery protocol using a JDBC connection to a shared database.
Expand Down Expand Up @@ -83,6 +84,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<JDBC_PING,DataSource>. " +
"If not null, this has precedence over datasource_jndi_name.")
protected String datasource_injecter_class;

/* --------------------------------------------- Fields ------------------------------------------------------ */

protected DataSource dataSource;
Expand All @@ -92,20 +97,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();
Expand Down Expand Up @@ -243,8 +280,8 @@ protected void readAll(Connection connection, List<Address> 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();
Expand All @@ -267,17 +304,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<JDBC_PING,DataSource> fun=(Function<JDBC_PING,DataSource>)obj;
return fun.apply(this);
}

// todo: check if connections should be cached (connection pool?)
protected Connection getConnection() {
if (dataSource == null) {
Connection connection;
Expand Down Expand Up @@ -407,43 +451,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";
Expand Down

0 comments on commit 56e4ad8

Please sign in to comment.