DatabaseConnectionSettings.java
/*
* Copyright 2018 Gregory Graham.
*
* Commercial licenses are available, please contact info@gregs.co.nz for details.
*
* This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
* To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/
* or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
*
* You are free to:
* Share - copy and redistribute the material in any medium or format
* Adapt - remix, transform, and build upon the material
*
* The licensor cannot revoke these freedoms as long as you follow the license terms.
* Under the following terms:
*
* Attribution -
* You must give appropriate credit, provide a link to the license, and indicate if changes were made.
* You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
* NonCommercial -
* You may not use the material for commercial purposes.
* ShareAlike -
* If you remix, transform, or build upon the material,
* you must distribute your contributions under the same license as the original.
* No additional restrictions -
* You may not apply legal terms or technological measures that legally restrict others from doing anything the
* license permits.
*
* Check the Creative Commons website for any details, legalese, and updates.
*/
package nz.co.gregs.dbvolution.databases;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import nz.co.gregs.dbvolution.annotations.DBTableName;
import nz.co.gregs.dbvolution.utility.StringCheck;
import nz.co.gregs.separatedstring.SeparatedString;
import nz.co.gregs.separatedstring.SeparatedStringBuilder;
/**
* A standardized collection of the database connection settings.
*
* <p>
* This object is a bean to provide a consistent way of defining a the
* connection details needed to connect to a database.</p>
*
* <p>
* Connection details can be grouped as username/password, URL, settings, and
* extras.</p>
*
* <p>
* Username and password are generally required to connect to a database and are
* provided to the connection separately from the url, settings, and extras.</p>
*
* <p>
* URL, settings, and extras are used to create the JDBC connection URL to the
* database and, with the username/password, to connection to the database.</p>
*
* <p>
* If the URL is supplied it will be used as provided and settings and extras
* will be ignored. This is reflected in the 2 standard constructors for
* DatabaseConnectionSettings:
* {@link #DatabaseConnectionSettings(java.lang.String, java.lang.String, java.lang.String) one for username/password/url}
* and
* {@link #DatabaseConnectionSettings(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.util.Map) one for username/password/settings/extras}.</p>
*
* <p>
* Without an explicit URL the settings (host, port, instance, database, schema)
* and extras will be combined to create the JDBC URL. This combination is
* deferred to the appropriate DBDatabase class and its version of null {@link DBDatabase#getUrlFromSettings(nz.co.gregs.dbvolution.databases.DatabaseConnectionSettings)
* }</p>
*
* <p>
* Extras are any miscellaneous and database specific settings that are added to
* the end of the JDBC URL to tweak the connection or database. Generally these
* are very database specific and will not work as expected for any other
* providers product.</p>
*
* <p>
* There is some confusion in the Database/JDBC world as to what some of the
* settings names (host, port, instance, database, schema) mean. For the
* purposes of DatabaseConnectionSettings:</p>
* <ul>
* <li>Host is the server name or Internet address of the database server, for
* instance db1.acme.com or 101.203.54.9.</li>
* <li>Port is the port number on the host that the database will accept
* connections from, for instance 1336</li>
* <li>Instance is the particular application or service that is providing the
* database if the database application is capable of running multiple instances
* on one server. Many databases are not and this setting should be ignored for
* those that cannot.</li>
* <li>Database is the named database within the application that the connection
* should use. Database is the central concept that all database providers
* implement. File based databases should use this to provide the file
* name.</li>
* <li>Schema is the level below database. It is optional or irrelevant for many
* RDBMSs or user setups. This is primarily where a user can create their own
* groupings below the database that they have been assigned to. Schema can also
* be specified using {@link DBTableName} when the schema name is
* unchanging.</li>
* </ul>
*
*
* @author Gregory Graham
*/
public class DatabaseConnectionSettings implements Serializable {
private static final long serialVersionUID = 1L;
private String url = "";
private String host = "";
private String port = "";
private String instance = "";
private String database = "";
private String username = "";
private String password = "";
private String schema = "";
private final HashMap<String, String> extras = new HashMap<>();
private final ArrayList<String> clusterHosts = new ArrayList<String>();
private String dbdatabase = "";
private String label = "";
private DataSource dataSource = null;
private String protocol;
private static final String FIELD_SEPARATOR = "<DCS FIELD>";
private static final String TOSTRING_SEPARATOR = ", ";
private String filename = "";
public static DatabaseConnectionSettings newSettings() {
return new DatabaseConnectionSettings();
}
private String encoded;
public DatabaseConnectionSettings() {
super();
}
public DatabaseConnectionSettings(DatabaseConnectionSettings dcs) {
super();
this.copy(dcs);
}
@Override
public String toString() {
SeparatedString toStringer = getToStringer();
toStringer.addAll(
StringCheck.check(getDbdatabaseClass()),
StringCheck.check(getHost()),
StringCheck.check(getPort()),
StringCheck.check(getInstance()),
StringCheck.check(getDatabaseName()),
StringCheck.check(getSchema()),
StringCheck.check(getUrl()),
StringCheck.check(getUsername()),
StringCheck.check(getPassword()),
StringCheck.check(getLabel()),
StringCheck.check(getFilename()),
StringCheck.check(encodeClusterHosts(getClusterHosts())),
StringCheck.check(encodeExtras(getExtras())));
return toStringer.encode();
}
/**
* Change the settings into and encoded string for use with {@link #decode(java.lang.String)
* }.
*
* <p>
* Includes username and password.</p>
*
* @return encoded settings suitable for decoding.
*/
public synchronized String encode() {
if (StringCheck.isEmptyOrNull(encoded)) {
List<DatabaseConnectionSettings> hosts = getClusterHosts();
String encodedHosts = encodeClusterHosts(hosts);
Map<String, String> gotExtras = getExtras();
String encodedExtras = encodeExtras(gotExtras);
SeparatedString encoder = getEncoder();
encoder.add(StringCheck.check(getDbdatabaseClass()));
encoder.add(StringCheck.check(getHost()));
encoder.add(StringCheck.check(getPort()));
encoder.add(StringCheck.check(getInstance()));
encoder.add(StringCheck.check(getDatabaseName()));
encoder.add(StringCheck.check(getSchema()));
encoder.add(StringCheck.check(getUrl()));
encoder.add(StringCheck.check(getUsername()));
encoder.add(StringCheck.check(getPassword()));
encoder.add(StringCheck.check(getLabel()));
encoder.add(StringCheck.check(getFilename()));
encoder.add(StringCheck.check(encodedHosts));
encoder.add(StringCheck.check(encodedExtras));
encoded = encoder.encode();
}
return encoded;
}
private static SeparatedString getEncoder() {
return SeparatedStringBuilder
.forSeparator(FIELD_SEPARATOR)
.withEscapeChar("\\")
.withPrefix("DATABASECONNECTIONSETTINGS: ");
}
private static SeparatedString getToStringer() {
return SeparatedStringBuilder.forSeparator(TOSTRING_SEPARATOR).withEscapeChar("\\").withPrefix("DATABASECONNECTIONSETTINGS: ");
}
public static DatabaseConnectionSettings decode(String encodedSettings) {
DatabaseConnectionSettings settings = new DatabaseConnectionSettings();
SeparatedString encoder = getEncoder();
List<String> decoded = encoder.decode(encodedSettings);
String[] data = decoded.toArray(new String[0]);
if (data.length > 0) {
settings.setDbdatabaseClass(data[0]);
if (data.length > 1) {
settings.setHost(data[1]);
if (data.length > 2) {
settings.setPort(data[2]);
if (data.length > 3) {
settings.setInstance(data[3]);
if (data.length > 4) {
settings.setDatabaseName(data[4]);
if (data.length > 5) {
settings.setSchema(data[5]);
if (data.length > 6) {
settings.setUrl(data[6]);
if (data.length > 7) {
settings.setUsername(data[7]);
if (data.length > 8) {
settings.setPassword(data[8]);
if (data.length > 9) {
settings.setLabel(data[9]);
if (data.length > 10) {
settings.setFilename(data[10]);
if (data.length > 11) {
settings.setClusterHosts(decodeClusterHosts(data[11]));
if (data.length > 12) {
settings.setExtras(decodeExtras(data[12]));
}
}
}
}
}
}
}
}
}
}
}
}
}
return settings;
}
public boolean equals(DatabaseConnectionSettings obj) {
return this.encode().equals(obj.encode());
}
public boolean notEquals(DatabaseConnectionSettings obj) {
return !this.encode().equals(obj.encode());
}
/**
* A standardized collection of the database connection settings.
*
* <p>
* This object is a bean to provide a consistent way of defining a the
* connection details needed to connect to a database.</p>
*
* <p>
* Connection details can be grouped as username/password, URL, settings, and
* extras.</p>
*
* <p>
* Username and password are generally required to connect to a database and
* are provided to the connection separately from the url, settings, and
* extras.</p>
*
* <p>
* URL, settings, and extras are used to create the JDBC connection URL to the
* database and, with the username/password, to connection to the
* database.</p>
*
* <p>
* If the URL is supplied it will be used as provided and settings and extras
* will be ignored. This is reflected in the 2 standard constructors for
* DatabaseConnectionSettings:
* {@link #DatabaseConnectionSettings(java.lang.String, java.lang.String, java.lang.String) one for username/password/url}
* and
* {@link #DatabaseConnectionSettings(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.util.Map) one for username/password/settings/extras}.</p>
*
* <p>
* Without an explicit URL the settings (host, port, instance, database,
* schema) and extras will be combined to create the JDBC URL. This
* combination is deferred to the appropriate DBDatabase class and its version
* of null {@link DBDatabase#getUrlFromSettings(nz.co.gregs.dbvolution.databases.DatabaseConnectionSettings)
* }</p>
*
* <p>
* Extras are any miscellaneous and database specific settings that are added
* to the end of the JDBC URL to tweak the connection or database. Generally
* these are very database specific and will not work as expected for any
* other providers product.</p>
*
* <p>
* There is some confusion in the Database/JDBC world as to what some of the
* settings names (host, port, instance, database, schema) mean. For the
* purposes of DatabaseConnectionSettings:</p>
* <ul>
* <li>Host is the server name or Internet address of the database server, for
* instance db1.acme.com or 101.203.54.9.</li>
* <li>Port is the port number on the host that the database will accept
* connections from, for instance 1336</li>
* <li>Instance is the particular application or service that is providing the
* database if the database application is capable of running multiple
* instances on one server. Many databases are not and this setting should be
* ignored for those that cannot.</li>
* <li>Database is the named database within the application that the
* connection should use. Database is the central concept that all database
* providers implement. File based databases should use this to provide the
* file name.</li>
* <li>Schema is the level below database. It is optional or irrelevant for
* many RDBMSs or user setups. This is primarily where a user can create their
* own groupings below the database that they have been assigned to. Schema
* can also be specified using {@link DBTableName} when the schema name is
* unchanging.</li>
* </ul>
*
*
* @author Gregory Graham
* @param url the JDBC URL to connect to the database
* @param username the username for logging in to the database
* @param password the password for the database user
*/
public DatabaseConnectionSettings(String url, String username, String password) {
super();
this.url = url;
this.username = username;
this.password = password;
}
/**
* A standardized collection of the database connection settings.
*
* <p>
* This object is a bean to provide a consistent way of defining a the
* connection details needed to connect to a database.</p>
*
* <p>
* Connection details can be grouped as username/password, URL, settings, and
* extras.</p>
*
* <p>
* Username and password are generally required to connect to a database and
* are provided to the connection separately from the url, settings, and
* extras.</p>
*
* <p>
* URL, settings, and extras are used to create the JDBC connection URL to the
* database and, with the username/password, to connection to the
* database.</p>
*
* <p>
* If the URL is supplied it will be used as provided and settings and extras
* will be ignored. This is reflected in the 2 standard constructors for
* DatabaseConnectionSettings:
* {@link #DatabaseConnectionSettings(java.lang.String, java.lang.String, java.lang.String) one for username/password/url}
* and
* {@link #DatabaseConnectionSettings(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.util.Map) one for username/password/settings/extras}.</p>
*
* <p>
* Without an explicit URL the settings (host, port, instance, database,
* schema) and extras will be combined to create the JDBC URL. This
* combination is deferred to the appropriate DBDatabase class and its version
* of null {@link DBDatabase#getUrlFromSettings(nz.co.gregs.dbvolution.databases.DatabaseConnectionSettings)
* }</p>
*
* <p>
* Extras are any miscellaneous and database specific settings that are added
* to the end of the JDBC URL to tweak the connection or database. Generally
* these are very database specific and will not work as expected for any
* other providers product.</p>
*
* <p>
* There is some confusion in the Database/JDBC world as to what some of the
* settings names (host, port, instance, database, schema) mean. For the
* purposes of DatabaseConnectionSettings:</p>
* <ul>
* <li>Host is the server name or Internet address of the database server, for
* instance db1.acme.com or 101.203.54.9.</li>
* <li>Port is the port number on the host that the database will accept
* connections from, for instance 1336</li>
* <li>Instance is the particular application or service that is providing the
* database if the database application is capable of running multiple
* instances on one server. Many databases are not and this setting should be
* ignored for those that cannot.</li>
* <li>Database is the named database within the application that the
* connection should use. Database is the central concept that all database
* providers implement. File based databases should use this to provide the
* file name.</li>
* <li>Schema is the level below database. It is optional or irrelevant for
* many RDBMSs or user setups. This is primarily where a user can create their
* own groupings below the database that they have been assigned to. Schema
* can also be specified using {@link DBTableName} when the schema name is
* unchanging.</li>
* </ul>
*
*
* @author Gregory Graham
* @param label an arbitrary label to identify the database
* @param url the JDBC URL to connect to the database
* @param username the username for logging in to the database
* @param password the password for the database user
*/
public DatabaseConnectionSettings(String url, String username, String password, String label) {
super();
this.label = label;
this.url = url;
this.username = username;
this.password = password;
}
/**
* A standardized collection of the database connection settings.
*
* <p>
* This object is a bean to provide a consistent way of defining a the
* connection details needed to connect to a database.</p>
*
* <p>
* Connection details can be grouped as username/password, URL, settings, and
* extras.</p>
*
* <p>
* Username and password are generally required to connect to a database and
* are provided to the connection separately from the url, settings, and
* extras.</p>
*
* <p>
* URL, settings, and extras are used to create the JDBC connection URL to the
* database and, with the username/password, to connection to the
* database.</p>
*
* <p>
* If the URL is supplied it will be used as provided and settings and extras
* will be ignored. This is reflected in the 2 standard constructors for
* DatabaseConnectionSettings:
* {@link #DatabaseConnectionSettings(java.lang.String, java.lang.String, java.lang.String) one for username/password/url}
* and
* {@link #DatabaseConnectionSettings(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.util.Map) one for username/password/settings/extras}.</p>
*
* <p>
* Without an explicit URL the settings (host, port, instance, database,
* schema) and extras will be combined to create the JDBC URL. This
* combination is deferred to the appropriate DBDatabase class and its version
* of null {@link DBDatabase#getUrlFromSettings(nz.co.gregs.dbvolution.databases.DatabaseConnectionSettings)
* }</p>
*
* <p>
* Extras are any miscellaneous and database specific settings that are added
* to the end of the JDBC URL to tweak the connection or database. Generally
* these are very database specific and will not work as expected for any
* other providers product.</p>
*
* <p>
* There is some confusion in the Database/JDBC world as to what some of the
* settings names (host, port, instance, database, schema) mean. For the
* purposes of DatabaseConnectionSettings:</p>
* <ul>
* <li>Host is the server name or Internet address of the database server, for
* instance db1.acme.com or 101.203.54.9.</li>
* <li>Port is the port number on the host that the database will accept
* connections from, for instance 1336</li>
* <li>Instance is the particular application or service that is providing the
* database if the database application is capable of running multiple
* instances on one server. Many databases are not and this setting should be
* ignored for those that cannot.</li>
* <li>Database is the named database within the application that the
* connection should use. Database is the central concept that all database
* providers implement. File based databases should use this to provide the
* file name.</li>
* <li>Schema is the level below database. It is optional or irrelevant for
* many RDBMSs or user setups. This is primarily where a user can create their
* own groupings below the database that they have been assigned to. Schema
* can also be specified using {@link DBTableName} when the schema name is
* unchanging.</li>
* </ul>
*
*
* @author Gregory Graham
* @param label and arbitrary name for the database
* @param host the hostname of the database server
* @param port the port used to connect to the database
* @param instance the database instance to use
* @param database the name of the database in the instance
* @param schema the schema to use in the database
* @param username the username for logging in to the database
* @param password the password for the database user
* @param extras any other database specific settings
*/
public DatabaseConnectionSettings(String host, String port, String instance, String database, String schema, String username, String password, Map<String, String> extras, String label) {
super();
this.label = label;
this.host = host;
this.port = port;
this.instance = instance;
this.database = database;
this.schema = schema;
this.username = username;
this.password = password;
this.extras.putAll(extras);
}
/**
* A standardized collection of the database connection settings.
*
* <p>
* This object is a bean to provide a consistent way of defining a the
* connection details needed to connect to a database.</p>
*
* <p>
* Connection details can be grouped as username/password, URL, settings, and
* extras.</p>
*
* <p>
* Username and password are generally required to connect to a database and
* are provided to the connection separately from the url, settings, and
* extras.</p>
*
* <p>
* URL, settings, and extras are used to create the JDBC connection URL to the
* database and, with the username/password, to connection to the
* database.</p>
*
* <p>
* If the URL is supplied it will be used as provided and settings and extras
* will be ignored. This is reflected in the 2 standard constructors for
* DatabaseConnectionSettings:
* {@link #DatabaseConnectionSettings(java.lang.String, java.lang.String, java.lang.String) one for username/password/url}
* and
* {@link #DatabaseConnectionSettings(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.util.Map) one for username/password/settings/extras}.</p>
*
* <p>
* Without an explicit URL the settings (host, port, instance, database,
* schema) and extras will be combined to create the JDBC URL. This
* combination is deferred to the appropriate DBDatabase class and its version
* of null {@link DBDatabase#getUrlFromSettings(nz.co.gregs.dbvolution.databases.DatabaseConnectionSettings)
* }</p>
*
* <p>
* Extras are any miscellaneous and database specific settings that are added
* to the end of the JDBC URL to tweak the connection or database. Generally
* these are very database specific and will not work as expected for any
* other providers product.</p>
*
* <p>
* There is some confusion in the Database/JDBC world as to what some of the
* settings names (host, port, instance, database, schema) mean. For the
* purposes of DatabaseConnectionSettings:</p>
* <ul>
* <li>Host is the server name or Internet address of the database server, for
* instance db1.acme.com or 101.203.54.9.</li>
* <li>Port is the port number on the host that the database will accept
* connections from, for instance 1336</li>
* <li>Instance is the particular application or service that is providing the
* database if the database application is capable of running multiple
* instances on one server. Many databases are not and this setting should be
* ignored for those that cannot.</li>
* <li>Database is the named database within the application that the
* connection should use. Database is the central concept that all database
* providers implement. File based databases should use this to provide the
* file name.</li>
* <li>Schema is the level below database. It is optional or irrelevant for
* many RDBMSs or user setups. This is primarily where a user can create their
* own groupings below the database that they have been assigned to. Schema
* can also be specified using {@link DBTableName} when the schema name is
* unchanging.</li>
* </ul>
*
*
* @author Gregory Graham
* @param host the hostname of the database server
* @param port the port used to connect to the database
* @param instance the database instance to use
* @param database the name of the database in the instance
* @param schema the schema to use in the database
* @param username the username for logging in to the database
* @param password the password for the database user
* @param extras any other database specific settings
*/
public DatabaseConnectionSettings(String host, String port, String instance, String database, String schema, String username, String password, Map<String, String> extras) {
super();
this.host = host;
this.port = port;
this.instance = instance;
this.database = database;
this.schema = schema;
this.username = username;
this.password = password;
this.extras.putAll(extras);
}
public static DatabaseConnectionSettings getSettingsfromSystemUsingPrefix(String prefix) {
DatabaseConnectionSettings settings = new DatabaseConnectionSettings();
settings.setUrl(System.getProperty(prefix + ".url"));
settings.setLabel(System.getProperty(prefix + ".label"));
settings.setDbdatabaseClass(System.getProperty(prefix + ".dbdatabase"));
settings.setUsername(System.getProperty(prefix + ".username"));
settings.setPassword(System.getProperty(prefix + ".password"));
settings.setProtocol(System.getProperty(prefix + ".protocol"));
settings.setHost(System.getProperty(prefix + ".host"));
settings.setPort(System.getProperty(prefix + ".port"));
settings.setInstance(System.getProperty(prefix + ".instance"));
settings.setDatabaseName(System.getProperty(prefix + ".database"));
settings.setSchema(System.getProperty(prefix + ".schema"));
settings.setFilename(StringCheck.check(
System.getProperty(prefix + ".filename"),
System.getProperty(prefix + ".file"),
System.getProperty(prefix + ".filepath")
)
);
settings.setClusterHosts(decodeClusterHosts(System.getProperty(prefix + ".clusterhosts")));
final String extrasFound = System.getProperty(prefix + ".extras");
final Map<String, String> decodedExtras = decodeExtras(extrasFound);
settings.mergeExtras(decodedExtras); // use merge to preserve default extras
return settings;
}
public final void copy(DatabaseConnectionSettings newSettings) {
copySimpleFields(newSettings);
this.setExtras(newSettings.getExtras());
}
public void merge(DatabaseConnectionSettings settings) {
clearCachedValues();
copySimpleFields(settings);
this.mergeExtras(settings.getExtras());
}
private void copySimpleFields(DatabaseConnectionSettings newSettings) {
this.setDataSource(newSettings.getDataSource());
this.setDatabaseName(newSettings.getDatabaseName());
this.setFilename(newSettings.getFilename());
this.setDbdatabaseClass(newSettings.getDbdatabaseClass());
this.setHost(newSettings.getHost());
this.setInstance(newSettings.getInstance());
this.setLabel(newSettings.getLabel());
this.setPassword(newSettings.getPassword());
this.setPort(newSettings.getPort());
this.setProtocol(newSettings.getProtocol());
this.setSchema(newSettings.getSchema());
this.setUrl(newSettings.getUrl());
this.setUsername(newSettings.getUsername());
this.setClusterHosts(newSettings.getClusterHosts());
}
/**
* Create the DBDatabase described by these settings
*
* @return the DBDatabase
* @throws ClassNotFoundException all database need an accessible default
* constructor
* @throws NoSuchMethodException all database need an accessible default
* constructor
* @throws SecurityException all database need an accessible default
* constructor
* @throws InstantiationException all database need an accessible default
* constructor
* @throws IllegalAccessException all database need an accessible default
* constructor
* @throws IllegalArgumentException all database need an accessible default
* constructor
* @throws InvocationTargetException all database need an accessible default
* constructor
*/
public final DBDatabase createDBDatabase() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> dbDatabaseClass = Class.forName(this.getDbdatabaseClass());
Constructor<?> constructor = dbDatabaseClass.getConstructor(DatabaseConnectionSettings.class);
if (constructor == null) {
return null;
} else {
constructor.setAccessible(true);
Object newInstance = constructor.newInstance(this);
if (newInstance != null && DBDatabase.class.isInstance(newInstance)) {
return (DBDatabase) newInstance;
} else {
return null;
}
}
}
/**
* @return the url
*/
public final String getUrl() {
return url;
}
/**
* @return the host
*/
public final String getHost() {
return host;
}
/**
* @return the port
*/
public final String getPort() {
return port;
}
/**
* @return the instance
*/
public final String getInstance() {
return instance;
}
/**
* @return the database
*/
public final String getDatabaseName() {
return database;
}
/**
* @return the username
*/
public final String getUsername() {
return username;
}
/**
* @return the password
*/
public final String getPassword() {
return password;
}
/**
* @return the schema
*/
public final String getSchema() {
return schema;
}
/**
* @param url the url to set
* @return this instance
*/
public final DatabaseConnectionSettings setUrl(String url) {
clearCachedValues();
this.url = url == null ? "" : url;
return this;
}
/**
* @param host the host to set
* @return this instance
*/
public final DatabaseConnectionSettings setHost(String host) {
clearCachedValues();
this.host = host == null ? "" : host;
return this;
}
/**
* @param port the port to set
* @return this instance
*/
public final DatabaseConnectionSettings setPort(String port) {
clearCachedValues();
this.port = port == null ? "" : port;
return this;
}
/**
* @param instance the instance to set
* @return this instance
*/
public final DatabaseConnectionSettings setInstance(String instance) {
clearCachedValues();
this.instance = instance == null ? "" : instance;
return this;
}
/**
* @param database the database to set
* @return this instance
*/
public final DatabaseConnectionSettings setDatabaseName(String database) {
clearCachedValues();
this.database = database == null ? "" : database;
return this;
}
/**
* @param username the username to set
* @return this instance
*/
public final DatabaseConnectionSettings setUsername(String username) {
clearCachedValues();
this.username = username == null ? "" : username;
return this;
}
/**
* @param password the password to set
* @return this instance
*/
public final DatabaseConnectionSettings setPassword(String password) {
clearCachedValues();
this.password = password == null ? "" : password;
return this;
}
/**
* @param schema the schema to set
* @return this instance
*/
public final DatabaseConnectionSettings setSchema(String schema) {
clearCachedValues();
this.schema = schema == null ? "" : schema;
return this;
}
/**
* @return the extras
*/
public final Map<String, String> getExtras() {
return extras;
}
/**
* Removes all existing extras and adds the supplied values.
*
* @param newExtras extra settings for the database
* @return the extras
*/
public final DatabaseConnectionSettings setExtras(Map<String, String> newExtras) {
clearCachedValues();
extras.clear();
if (newExtras != null && !newExtras.isEmpty()) {
extras.putAll(newExtras);
}
return this;
}
/**
* Adds the supplied values to the extras map, retaining any existing entries
* and updating obsolete one.
*
* @param newExtras extra settings for the database
* @return the extras
*/
public final DatabaseConnectionSettings mergeExtras(Map<String, String> newExtras) {
clearCachedValues();
if (newExtras != null && !newExtras.isEmpty()) {
extras.putAll(newExtras);
}
return this;
}
/**
* Adds or replaces the new values to the existing extras.
*
* @param newExtras extra settings for the database
* @return the extras
*/
public final DatabaseConnectionSettings addExtras(Map<String, String> newExtras) {
clearCachedValues();
if (newExtras != null && !newExtras.isEmpty()) {
extras.putAll(newExtras);
}
return this;
}
public final String formatExtras(String prefix, String nameValueSeparator, String nameValuePairSeparator, String suffix) {
return SeparatedStringBuilder
.forSeparator(nameValuePairSeparator)
.withKeyValueSeparator(nameValueSeparator)
.withPrefix(prefix)
.withSuffix(suffix)
.addAll(extras)
.toString();
}
public static Map<String, String> decodeExtras(String extras, String prefix, String nameValueSeparator, String nameValuePairSeparator, String suffix) {
return SeparatedStringBuilder
.forSeparator(nameValuePairSeparator)
.withKeyValueSeparator(nameValueSeparator)
.withPrefix(prefix)
.withSuffix(suffix)
.parseToMap(extras);
}
private static SeparatedString clusterHostEncoder() {
return SeparatedStringBuilder
.forSeparator("|")
.withPrefix("<")
.withSuffix(">")
.withEscapeChar("!");
}
public static String encodeClusterHosts(List<DatabaseConnectionSettings> clusterHosts) {
SeparatedString csv = clusterHostEncoder();
for (DatabaseConnectionSettings clusterHost : clusterHosts) {
String encoded = clusterHost.encode();
csv.add(encoded);
}
String result = csv.toString();
return result;
}
public static List<DatabaseConnectionSettings> decodeClusterHosts(String clusterHosts) {
final ArrayList<DatabaseConnectionSettings> results = new ArrayList<>(0);
final SeparatedString clusterHostEncoder = clusterHostEncoder();
List<String> hosts = clusterHostEncoder.parseToList(clusterHosts);
for (String host : hosts) {
try {
DatabaseConnectionSettings decodedHost = decode(host);
results.add(decodedHost);
} catch (Exception e) {
System.out.println("Error while decoding cluster hosts: " + e.getMessage());
}
}
return results;
}
public final DatabaseConnectionSettings setDbdatabaseClass(String canonicalNameOfADBDatabaseSubclass) {
clearCachedValues();
this.dbdatabase = canonicalNameOfADBDatabaseSubclass;
return this;
}
public final String getDbdatabaseClass() {
return this.dbdatabase;
}
/**
* A label for the database for reference within an application.
*
* <p>
* This label has no effect on the actual database connection.
*
* @param label an arbitrary name for the database
* @return this instance
*/
public final DatabaseConnectionSettings setLabel(String label) {
clearCachedValues();
this.label = label;
return this;
}
/**
* A label for the database for reference within an application.
*
* <p>
* This label has no effect on the actual database connection.
*
*
* @return the label set for the database
*/
public final String getLabel() {
return label;
}
public final DatabaseConnectionSettings setDataSource(DataSource ds) {
clearCachedValues();
dataSource = ds;
return this;
}
public final DataSource getDataSource() {
return dataSource;
}
public final DatabaseConnectionSettings setProtocol(String protocol) {
clearCachedValues();
this.protocol = protocol;
return this;
}
public final String getProtocol() {
return protocol;
}
public final DatabaseConnectionSettings setDefaultExtras(Map<String, String> defaultConfigurationExtras) {
clearCachedValues();
defaultConfigurationExtras.forEach((t, u) -> {
this.extras.putIfAbsent(t, u);
});
return this;
}
public final DatabaseConnectionSettings addExtra(String tag, String value) {
clearCachedValues();
this.extras.put(tag, value);
return this;
}
public final DatabaseConnectionSettings setFilename(String filename) {
clearCachedValues();
this.filename = filename;
return this;
}
public final String getFilename() {
return filename;
}
public final List<DatabaseConnectionSettings> getClusterHosts() {
ArrayList<DatabaseConnectionSettings> settings = new ArrayList<>();
for (String clusterHost : clusterHosts) {
var decoded = DatabaseConnectionSettings.decode(clusterHost);
settings.add(decoded);
}
return settings;
}
public final DatabaseConnectionSettings setClusterHosts(List<DatabaseConnectionSettings> clusterHosts) {
clearCachedValues();
this.clusterHosts.clear();
addAllClusterHosts(clusterHosts);
return this;
}
public final void addClusterHost(DatabaseConnectionSettings clusterHost) {
clearCachedValues();
if (clusterHost != null) {
final String newHost = clusterHost.encode();
if (!clusterHosts.contains(newHost)) {
this.clusterHosts.add(newHost);
}
}
}
public final void addAllClusterHosts(List<DatabaseConnectionSettings> clusterHosts) {
clearCachedValues();
if (clusterHosts != null) {
for (DatabaseConnectionSettings clusterHost : clusterHosts) {
this.addClusterHost(clusterHost);
}
}
}
public static String encodeExtras(Map<String, String> extras) {
SeparatedString encoder = extrasEncoder();
SeparatedString added = encoder.addAll(extras);
String encoded = added.encode();
return encoded;
}
public static Map<String, String> decodeExtras(String extras) {
return extrasEncoder()
.parseToMap(extras);
}
private static SeparatedString extrasEncoder() {
return SeparatedStringBuilder
.forSeparator(";")
.withKeyValueSeparator("=")
.withEscapeChar("!");
}
public boolean removeClusterHost(DatabaseConnectionSettings settings) {
clearCachedValues();
return this.clusterHosts.remove(settings.encode());
}
public String removeExtra(String key) {
clearCachedValues();
return this.extras.remove(key);
}
private void clearCachedValues() {
encoded = null;
}
}