blob: db5da272822056a8bda5a1fd57eb4a6671834fa0 [file] [log] [blame]
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (c) 2012-2014 Monty Program Ab
// Copyright (c) 2015-2021 MariaDB Corporation Ab
package org.mariadb.jdbc;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.locks.ReentrantLock;
import org.mariadb.jdbc.client.Client;
import org.mariadb.jdbc.client.impl.MultiPrimaryClient;
import org.mariadb.jdbc.client.impl.MultiPrimaryReplicaClient;
import org.mariadb.jdbc.client.impl.ReplayClient;
import org.mariadb.jdbc.client.impl.StandardClient;
import org.mariadb.jdbc.pool.Pools;
import org.mariadb.jdbc.util.VersionFactory;
/** MariaDB Driver */
public final class Driver implements java.sql.Driver {
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException e) {
// eat
}
}
/**
* Connect according to configuration
*
* @param configuration configuration
* @return a Connection
* @throws SQLException if connect fails
*/
public static Connection connect(Configuration configuration) throws SQLException {
ReentrantLock lock = new ReentrantLock();
Client client;
switch (configuration.haMode()) {
case LOADBALANCE:
case SEQUENTIAL:
client = new MultiPrimaryClient(configuration, lock);
break;
case REPLICATION:
// additional check
client = new MultiPrimaryReplicaClient(configuration, lock);
break;
default:
ClientInstance<Configuration, HostAddress, ReentrantLock, Boolean, Client> clientInstance =
(configuration.transactionReplay()) ? ReplayClient::new : StandardClient::new;
if (configuration.addresses().isEmpty()) {
// unix socket / windows pipe
client = clientInstance.apply(configuration, null, lock, false);
} else {
// loop until finding
SQLException lastException = null;
for (HostAddress host : configuration.addresses()) {
try {
client = clientInstance.apply(configuration, host, lock, false);
return new Connection(configuration, lock, client);
} catch (SQLException e) {
lastException = e;
}
}
throw lastException;
}
break;
}
return new Connection(configuration, lock, client);
}
@FunctionalInterface
private interface ClientInstance<T, U, V, W, R> {
R apply(T t, U u, V v, W w) throws SQLException;
}
/**
* Connect to the given connection string.
*
* @param url the url to connect to
* @return a connection
* @throws SQLException if it is not possible to connect
*/
public Connection connect(final String url, final Properties props) throws SQLException {
Configuration configuration = Configuration.parse(url, props);
if (configuration != null) {
if (configuration.pool()) {
return Pools.retrievePool(configuration).getPoolConnection().getConnection();
}
return connect(configuration);
}
return null;
}
/**
* returns true if the driver can accept the url.
*
* @param url the url to test
* @return true if the url is valid for this driver
*/
@Override
public boolean acceptsURL(String url) {
return Configuration.acceptsUrl(url);
}
/**
* Get the property info.
*
* @param url the url to get properties for
* @param info the info props
* @return all possible connector options
* @throws SQLException if there is a problem getting the property info
*/
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
Configuration conf = Configuration.parse(url, info);
if (conf == null) {
return new DriverPropertyInfo[0];
}
Properties propDesc = new Properties();
try (InputStream inputStream =
Driver.class.getClassLoader().getResourceAsStream("driver.properties")) {
propDesc.load(inputStream);
} catch (IOException io) {
// eat
}
List<DriverPropertyInfo> props = new ArrayList<>();
for (Field field : Configuration.Builder.class.getDeclaredFields()) {
if (!field.getName().startsWith("_")) {
try {
Field fieldConf = Configuration.class.getDeclaredField(field.getName());
fieldConf.setAccessible(true);
Object obj = fieldConf.get(conf);
String value = obj == null ? null : obj.toString();
DriverPropertyInfo propertyInfo = new DriverPropertyInfo(field.getName(), value);
propertyInfo.description = value == null ? "" : (String) propDesc.get(field.getName());
propertyInfo.required = false;
props.add(propertyInfo);
} catch (IllegalAccessException | NoSuchFieldException e) {
// eat error
}
}
}
return props.toArray(new DriverPropertyInfo[0]);
}
/**
* gets the major version of the driver.
*
* @return the major versions
*/
public int getMajorVersion() {
return VersionFactory.getInstance().getMajorVersion();
}
/**
* gets the minor version of the driver.
*
* @return the minor version
*/
public int getMinorVersion() {
return VersionFactory.getInstance().getMinorVersion();
}
/**
* checks if the driver is jdbc compliant.
*
* @return true since the driver is not compliant
*/
public boolean jdbcCompliant() {
return true;
}
public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException("Use logging parameters for enabling logging.");
}
}