org.mariadb.jdbc.internal.util.DefaultOptions Maven / Gradle / Ivy
Show all versions of mariadb-java-client-jre7 Show documentation
/*
*
* MariaDB Client for Java
*
* Copyright (c) 2012-2014 Monty Program Ab.
* Copyright (c) 2015-2017 MariaDB Ab.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this library; if not, write to Monty Program Ab [email protected].
*
* This particular MariaDB Client for Java file is work
* derived from a Drizzle-JDBC. Drizzle-JDBC file which is covered by subject to
* the following copyright and notice provisions:
*
* Copyright (c) 2009-2011, Marcus Eriksson
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* Neither the name of the driver nor the names of its contributors may not be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
*/
package org.mariadb.jdbc.internal.util;
import org.mariadb.jdbc.internal.util.constant.HaMode;
import java.util.Properties;
public enum DefaultOptions {
/**
* Database user name.
*/
USER("user", "1.0.0"),
/**
* Password of database user.
*/
PASSWORD("password", "1.0.0"),
CONNECT_TIMEOUT("connectTimeout", (Integer) null, 0, Integer.MAX_VALUE, "1.1.8"),
/**
* On Windows, specify named pipe name to connect to mysqld.exe.
*/
PIPE("pipe", "1.1.3"),
/**
* Allows to connect to database via Unix domain socket, if server allows it. The value is the path of Unix domain socket, i.e "socket"
* database parameter.
*/
LOCAL_SOCKET("localSocket", "1.1.4"),
/**
* Allowed to connect database via shared memory, if server allows it. The value is base name of the shared memory.
*/
SHARED_MEMORY("sharedMemory", "1.1.4"),
/**
* Sets corresponding option on the connection socket.
*/
TCP_NO_DELAY("tcpNoDelay", Boolean.TRUE, "1.0.0"),
/**
* Sets corresponding option on the connection socket.
*/
TCP_ABORTIVE_CLOSE("tcpAbortiveClose", Boolean.FALSE, "1.1.1"),
/**
* Hostname or IP address to bind the connection socket to a local (UNIX domain) socket.
*/
LOCAL_SOCKET_ADDRESS("localSocketAddress", "1.1.8"),
/**
* Defined the network socket timeout (SO_TIMEOUT) in milliseconds.
* 0 (default) disable this timeout
*/
SOCKET_TIMEOUT("socketTimeout", new Integer[]{10000, null, null, null, null, null}, 0, Integer.MAX_VALUE, "1.1.8"),
/**
* Session timeout is defined by the wait_timeout server variable.
* Setting interactiveClient to true will tell server to use the interactive_timeout server variable
*/
INTERACTIVE_CLIENT("interactiveClient", Boolean.FALSE, "1.1.8"),
/**
* If set to 'true', exception thrown during query execution contain query string.
*/
DUMP_QUERY_ON_EXCEPTION("dumpQueriesOnException", Boolean.TRUE, "1.1.0"),
/**
* Metadata ResultSetMetaData.getTableName() return the physical table name.
* "useOldAliasMetadataBehavior" permit to activate the legacy code that send the table alias if set.
*/
USE_OLD_ALIAS_METADATA_BEHAVIOR("useOldAliasMetadataBehavior", Boolean.FALSE, "1.1.9"),
/**
* If set to 'false', exception thrown during LOCAL INFILE if no InputStream has already been set.
*/
ALLOW_LOCAL_INFILE("allowLocalInfile", Boolean.TRUE, "1.2.1"),
/**
* var=value pairs separated by comma, mysql session variables, set upon establishing successful connection.
*/
SESSION_VARIABLES("sessionVariables", "1.1.0"),
/**
* The database precised in url will be created if doesn't exist.
* (legacy alias "createDB")
*/
CREATE_DATABASE_IF_NOT_EXISTS("createDatabaseIfNotExist", Boolean.FALSE, "1.1.8"),
/**
* Defined the server time zone.
* to use only if jre server as a different time implementation of the server.
* (best to have the same server time zone when possible)
*/
SERVER_TIMEZONE("serverTimezone", "1.1.8"),
/**
* DatabaseMetaData use current catalog if null.
*/
NULL_CATALOG_MEANS_CURRENT("nullCatalogMeansCurrent", Boolean.TRUE, "1.1.8"),
/**
* Datatype mapping flag, handle MySQL Tiny as BIT(boolean).
*/
TINY_INT_IS_BIT("tinyInt1isBit", Boolean.TRUE, "1.0.0"),
/**
* Year is date type, rather than numerical.
*/
YEAR_IS_DATE_TYPE("yearIsDateType", Boolean.TRUE, "1.0.0"),
/**
* Force SSL on connection.
* (legacy alias "useSSL")
*/
USE_SSL("useSsl", Boolean.FALSE, "1.1.0"),
/**
* allow compression in MySQL Protocol.
*/
USER_COMPRESSION("useCompression", Boolean.FALSE, "1.0.0"),
/**
* Allows multiple statements in single executeQuery.
*/
ALLOW_MULTI_QUERIES("allowMultiQueries", Boolean.FALSE, "1.0.0"),
/**
* rewrite batchedStatement to have only one server call.
*/
REWRITE_BATCHED_STATEMENTS("rewriteBatchedStatements", Boolean.FALSE, "1.1.8"),
/**
* Sets corresponding option on the connection socket.
* Defaults to true since 1.6.0 (false before)
*/
TCP_KEEP_ALIVE("tcpKeepAlive", Boolean.TRUE, "1.0.0"),
/**
* set buffer size for TCP buffer (SO_RCVBUF).
*/
TCP_RCV_BUF("tcpRcvBuf", (Integer) null, 0, Integer.MAX_VALUE, "1.0.0"),
/**
* set buffer size for TCP buffer (SO_SNDBUF).
*/
TCP_SND_BUF("tcpSndBuf", (Integer) null, 0, Integer.MAX_VALUE, "1.0.0"),
/**
* to use custom socket factory, set it to full name of the class that implements javax.net.SocketFactory.
*/
SOCKET_FACTORY("socketFactory", "1.0.0"),
PIN_GLOBAL_TX_TO_PHYSICAL_CONNECTION("pinGlobalTxToPhysicalConnection", Boolean.FALSE, "1.1.8"),
/**
* When using SSL, do not check server's certificate.
*/
TRUST_SERVER_CERTIFICATE("trustServerCertificate", Boolean.FALSE, "1.1.1"),
/**
* Server's certificate in DER form, or server's CA certificate. Can be used in one of 3 forms, sslServerCert=/path/to/cert.pem
* (full path to certificate), sslServerCert=classpath:relative/cert.pem (relative to current classpath), or as verbatim DER-encoded certificate
* string "-----BEGIN CERTIFICATE-----".
*/
SERVER_SSL_CERT("serverSslCert", "1.1.3"),
/**
* Correctly handle subsecond precision in timestamps (feature available with MariaDB 5.3 and later).
* May confuse 3rd party components (Hibernated).
*/
USE_FRACTIONAL_SECONDS("useFractionalSeconds", Boolean.TRUE, "1.0.0"),
/**
* Driver must recreateConnection after a failover.
*/
AUTO_RECONNECT("autoReconnect", Boolean.FALSE, "1.2.0"),
/**
* After a master failover and no other master found, back on a read-only host ( throw exception if not).
*/
FAIL_ON_READ_ONLY("failOnReadOnly", Boolean.FALSE, "1.2.0"),
/**
* When using loadbalancing, the number of times the driver should cycle through available hosts, attempting to connect.
* Between cycles, the driver will pause for 250ms if no servers are available.
*/
RETRY_ALL_DOWN("retriesAllDown", 120, 0, Integer.MAX_VALUE, "1.2.0"),
/**
* When using failover, the number of times the driver should cycle silently through available hosts, attempting to connect.
* Between cycles, the driver will pause for 250ms if no servers are available.
* if set to 0, there will be no silent reconnection
*/
FAILOVER_LOOP_RETRIES("failoverLoopRetries", 120, 0, Integer.MAX_VALUE, "1.2.0"),
/**
* When in multiple hosts, after this time in second without used, verification that the connections haven't been lost.
* When 0, no verification will be done. Defaults to 0 (120 before 1.5.8 version)
*/
VALID_CONNECTION_TIMEOUT("validConnectionTimeout", 0, 0, Integer.MAX_VALUE, "1.2.0"),
/**
* time in second a server is blacklisted after a connection failure. default to 50s
*/
LOAD_BALANCE_BLACKLIST_TIMEOUT("loadBalanceBlacklistTimeout", 50, 0, Integer.MAX_VALUE, "1.2.0"),
/**
* enable/disable prepare Statement cache, default true.
*/
CACHEPREPSTMTS("cachePrepStmts", Boolean.TRUE, "1.3.0"),
/**
* This sets the number of prepared statements that the driver will cache per VM if "cachePrepStmts" is enabled.
* default to 250.
*/
PREPSTMTCACHESIZE("prepStmtCacheSize", 250, 0, Integer.MAX_VALUE, "1.3.0"),
/**
* This is the maximum length of a prepared SQL statement that the driver will cache if "cachePrepStmts" is enabled.
* default to 2048.
*/
PREPSTMTCACHESQLLIMIT("prepStmtCacheSqlLimit", 2048, 0, Integer.MAX_VALUE, "1.3.0"),
/**
* when in high availability, and switching to a read-only host, assure that this host is in read-only mode by
* setting session read-only.
* default to false
*/
ASSUREREADONLY("assureReadOnly", Boolean.FALSE, "1.3.0"),
/**
* if true (default) store date/timestamps according to client time zone.
* if false, store all date/timestamps in DB according to server time zone, and time information (that is a time difference), doesn't take
* timezone in account.
*/
USELEGACYDATETIMECODE("useLegacyDatetimeCode", Boolean.TRUE, "1.3.0"),
/**
* maximize Mysql compatibility.
* when using jdbc setDate(), will store date in client timezone, not in server timezone when useLegacyDatetimeCode = false.
* default to false.
*/
MAXIMIZEMYSQLCOMPATIBILITY("maximizeMysqlCompatibility", Boolean.FALSE, "1.3.0"),
/**
* useServerPrepStmts must prepared statements be prepared on server side, or just faked on client side.
* if rewriteBatchedStatements is set to true, this options will be set to false.
* default to false.
*/
USESERVERPREPSTMTS("useServerPrepStmts", Boolean.FALSE, "1.3.0"),
/**
* File path of the trustStore file (similar to java System property "javax.net.ssl.trustStore").
* Use the specified keystore for trusted root certificates.
* When set, overrides serverSslCert.
*
* (legacy alias trustCertificateKeyStoreUrl)
*/
TRUST_CERTIFICATE_KEYSTORE_URL("trustStore", "1.3.0"),
/**
* Password for the trusted root certificate file (similar to java System property "javax.net.ssl.trustStorePassword").
*
* (legacy alias trustCertificateKeyStorePassword)
*/
TRUST_CERTIFICATE_KEYSTORE_PASSWORD("trustStorePassword", "1.3.0"),
/**
* File path of the keyStore file that contain client private key store and associate certificates
* (similar to java System property "javax.net.ssl.keyStore", but ensure that only the private key's entries are used).
* (legacy alias clientCertificateKeyStoreUrl)
*/
CLIENT_CERTIFICATE_KEYSTORE_URL("keyStore", "1.3.0"),
/**
* Password for the client certificate keystore (similar to java System property "javax.net.ssl.keyStorePassword").
* (legacy alias clientCertificateKeyStorePassword)
*/
CLIENT_CERTIFICATE_KEYSTORE_PASSWORD("keyStorePassword", "1.3.0"),
/**
* Password for the private key contain in client certificate keystore.
* needed only in case private key password differ from keyStore password.
*/
PRIVATE_KEYS_PASSWORD("keyPassword", "1.5.3"),
/**
* Force TLS/SSL protocol to a specific set of TLS versions (comma separated list)
* example : "TLSv1, TLSv1.1, TLSv1.2"
*/
ENABLED_SSL_PROTOCOL_SUITES("enabledSslProtocolSuites", "1.5.0"),
/**
* Force TLS/SSL cipher. (comma separated list)
* example : "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"
*/
ENABLED_SSL_CIPHER_SUITES("enabledSslCipherSuites", "1.5.0"),
/**
* When executing batch queries, must batch continue on error.
* default to true.
*/
CONTINUE_BATCH_ON_ERROR("continueBatchOnError", Boolean.TRUE, "1.4.0"),
/**
* Truncation error ("Data truncated for column '%' at row %", "Out of range value for column '%' at row %") will be thrown as error,
* and not as warning.
*/
JDBCOMPLIANTRUNCATION("jdbcCompliantTruncation", Boolean.TRUE, "1.4.0"),
/**
* enable/disable callable Statement cache, default true.
*/
CACHE_CALLABLE_STMTS("cacheCallableStmts", Boolean.TRUE, "1.4.0"),
/**
* This sets the number of callable statements that the driver will cache per VM if "cacheCallableStmts" is enabled.
* default to 150.
*/
CALLABLE_STMT_CACHE_SIZE("callableStmtCacheSize", 150, 0, Integer.MAX_VALUE, "1.4.0"),
/**
* Indicate to server some client information in a key;value pair.
* for example connectionAttributes=key1:value1,key2,value2.
* Those information can be retrieved on server within tables mysql.session_connect_attrs and mysql.session_account_connect_attrs.
* This can permit from server an identification of client.
*/
CONNECTION_ATTRIBUTES("connectionAttributes", "1.4.0"),
/**
* PreparedStatement.executeBatch() will send many QUERY before reading result packets.
* default to true.
* (null is considered true. this permit to know if option was explicitly set)
*/
USE_BATCH_MULTI_SEND("useBatchMultiSend", (Boolean) null, "1.5.0"),
/**
* When using useBatchMultiSend, indicate maximum query that can be send at a time.
* default to 100
*/
USE_BATCH_MULTI_SEND_NUMBER("useBatchMultiSendNumber", 100, 1, Integer.MAX_VALUE, "1.5.0"),
/**
* Enable log information. require Slf4j version > 1.4 dependency.
* log informations :
* - info : query log
* default to false.
*/
LOGGING("log", Boolean.FALSE, "1.5.0"),
/**
* log query execution time.
* (legacy alias alias profileSQL)
*/
PROFILESQL("profileSql", Boolean.FALSE, "1.5.0"),
/**
* Max query log size.
* default to 1024.
*/
MAX_QUERY_LOG_SIZE("maxQuerySizeToLog", 1024, 0, Integer.MAX_VALUE, "1.5.0"),
/**
* Will log query with execution time superior to this value (if defined )
* default to null.
*/
SLOW_QUERY_TIME("slowQueryThresholdNanos", (Long) null, 0L, Long.MAX_VALUE, "1.5.0"),
/**
* Indicate password encoding charset. If not set, driver use platform's default charset.
* default to null.
*/
PASSWORD_CHARACTER_ENCODING("passwordCharacterEncoding", "1.5.9"),
/**
* Fast connection creation (recommended if not using authentication plugins)
* default to true.
* (null is considered true. this permit to know if option was explicitly set)
*/
PIPELINE_AUTH("usePipelineAuth", (Boolean) null, "1.6.0"),
/**
* When closing a statement that is fetching result-set (using setFetchSize),
* kill query to avoid having to read remaining rows.
*/
KILL_FETCH_STMT("killFetchStmtOnClose", Boolean.TRUE, "1.6.0"),
/**
* Driver will save the last 16 MySQL packet exchanges (limited to first 1000 bytes).
* Hexadecimal value of those packet will be added to stacktrace when an IOException occur.
* This options has no performance incidence (< 1 microseconds per query) but driver will then take 16kb more memory.
*/
ENABLE_PACKET_DEBUG("enablePacketDebug", Boolean.FALSE, "1.6.0");
protected final String name;
protected final Object objType;
protected final Object defaultValue;
protected final Object minValue;
protected final Object maxValue;
protected final String implementationVersion;
protected Object value = null;
DefaultOptions(String name, String implementationVersion) {
this.name = name;
this.implementationVersion = implementationVersion;
objType = String.class;
defaultValue = null;
minValue = null;
maxValue = null;
}
DefaultOptions(String name, Boolean defaultValue, String implementationVersion) {
this.name = name;
this.objType = Boolean.class;
this.defaultValue = defaultValue;
this.implementationVersion = implementationVersion;
minValue = null;
maxValue = null;
}
DefaultOptions(String name, Integer defaultValue, Integer minValue, Integer maxValue, String implementationVersion) {
this.name = name;
this.objType = Integer.class;
this.defaultValue = defaultValue;
this.minValue = minValue;
this.maxValue = maxValue;
this.implementationVersion = implementationVersion;
}
DefaultOptions(String name, Long defaultValue, Long minValue, Long maxValue, String implementationVersion) {
this.name = name;
this.objType = Long.class;
this.defaultValue = defaultValue;
this.minValue = minValue;
this.maxValue = maxValue;
this.implementationVersion = implementationVersion;
}
DefaultOptions(String name, Integer[] defaultValue, Integer minValue, Integer maxValue, String implementationVersion) {
this.name = name;
this.objType = Integer.class;
this.defaultValue = defaultValue;
this.minValue = minValue;
this.maxValue = maxValue;
this.implementationVersion = implementationVersion;
}
public static Options defaultValues(HaMode haMode) {
return parse(haMode, "", new Properties());
}
public static Options parse(HaMode haMode, String urlParameters, Options options) {
Properties prop = new Properties();
return parse(haMode, urlParameters, prop, options);
}
public static Options parse(HaMode haMode, String urlParameters, Properties properties) {
return parse(haMode, urlParameters, properties, null);
}
/**
* Parse additional properties .
*
* @param haMode current haMode.
* @param urlParameters options defined in url
* @param properties options defined by properties
* @param options initial options
* @return options
*/
public static Options parse(HaMode haMode, String urlParameters, Properties properties, Options options) {
if (urlParameters != null && !urlParameters.isEmpty()) {
String[] parameters = urlParameters.split("&");
for (String parameter : parameters) {
int pos = parameter.indexOf('=');
if (pos == -1) {
throw new IllegalArgumentException("Invalid connection URL, expected key=value pairs, found " + parameter);
}
if (!properties.containsKey(parameter.substring(0, pos))) {
properties.setProperty(parameter.substring(0, pos), parameter.substring(pos + 1));
}
}
}
return parse(haMode, properties, options);
}
private static Options parse(HaMode haMode, Properties properties, Options options) {
boolean initial = false;
if (options == null) {
options = new Options();
initial = true;
}
try {
for (DefaultOptions o : DefaultOptions.values()) {
String propertyValue = properties.getProperty(o.name);
//Handle alias
if (propertyValue == null) {
switch (o.name) {
case "createDatabaseIfNotExist":
propertyValue = properties.getProperty("createDB");
break;
case "useSsl":
propertyValue = properties.getProperty("useSSL");
break;
case "profileSql":
propertyValue = properties.getProperty("profileSQL");
break;
case "enabledSslCipherSuites":
propertyValue = properties.getProperty("enabledSSLCipherSuites");
break;
case "trustStorePassword":
propertyValue = properties.getProperty("trustCertificateKeyStorePassword");
break;
case "trustStore":
propertyValue = properties.getProperty("trustCertificateKeyStoreUrl");
break;
case "keyStorePassword":
propertyValue = properties.getProperty("clientCertificateKeyStorePassword");
break;
case "keyStore":
propertyValue = properties.getProperty("clientCertificateKeyStoreUrl");
break;
default:
//no alias
}
}
if (propertyValue != null) {
if (o.objType.equals(String.class)) {
Options.class.getField(o.name).set(options, propertyValue);
} else if (o.objType.equals(Boolean.class)) {
switch (propertyValue.toLowerCase()) {
case "1":
case "true":
Options.class.getField(o.name).set(options, Boolean.TRUE);
break;
case "0":
case "false":
Options.class.getField(o.name).set(options, Boolean.FALSE);
break;
default:
throw new IllegalArgumentException("Optional parameter " + o.name
+ " must be boolean (true/false or 0/1) was \"" + propertyValue + "\"");
}
} else if (o.objType.equals(Integer.class)) {
try {
Integer value = Integer.parseInt(propertyValue);
if (value.compareTo((Integer) o.minValue) < 0 || value.compareTo((Integer) o.maxValue) > 0) {
throw new IllegalArgumentException("Optional parameter " + o.name + " must be greater or equal to " + o.minValue
+ ((((Integer) o.maxValue).intValue() != Integer.MAX_VALUE) ? " and smaller than " + o.maxValue : " ")
+ ", was \"" + propertyValue + "\"");
}
Options.class.getField(o.name).set(options, value);
} catch (NumberFormatException n) {
throw new IllegalArgumentException("Optional parameter " + o.name + " must be Integer, was \"" + propertyValue + "\"");
}
} else if (o.objType.equals(Long.class)) {
try {
Long value = Long.parseLong(propertyValue);
if (value.compareTo((Long) o.minValue) < 0 || value.compareTo((Long) o.maxValue) > 0) {
throw new IllegalArgumentException("Optional parameter " + o.name + " must be greater or equal to " + o.minValue
+ ((((Long) o.maxValue).intValue() != Long.MAX_VALUE) ? " and smaller than " + o.maxValue : " ")
+ ", was \"" + propertyValue + "\"");
}
Options.class.getField(o.name).set(options, value);
} catch (NumberFormatException n) {
throw new IllegalArgumentException("Optional parameter " + o.name + " must be Long, was \"" + propertyValue + "\"");
}
}
} else {
if (initial) {
if (o.defaultValue instanceof Integer[]) {
Options.class.getField(o.name).set(options, ((Integer[]) o.defaultValue)[haMode.ordinal()]);
} else {
Options.class.getField(o.name).set(options, o.defaultValue);
}
}
}
}
} catch (NoSuchFieldException | IllegalAccessException n) {
n.printStackTrace();
} catch (SecurityException s) {
//only for jws, so never thrown
throw new IllegalArgumentException("Security too restrictive : " + s.getMessage());
}
//not compatible options
//disable use server prepare id using client rewrite
if (options.rewriteBatchedStatements) {
options.useServerPrepStmts = false;
options.cachePrepStmts = false;
}
//pipe cannot use read and write socket simultaneously
if (options.pipe != null) {
options.useBatchMultiSend = false;
options.usePipelineAuth = false;
}
return options;
}
}