org.voltdb.jdbc.Driver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of voltdbclient Show documentation
Show all versions of voltdbclient Show documentation
VoltDB client interface libraries
/* This file is part of VoltDB.
* Copyright (C) 2008-2017 VoltDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with VoltDB. If not, see .
*/
package org.voltdb.jdbc;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import org.voltcore.utils.ssl.SSLConfiguration;
public class Driver implements java.sql.Driver
{
public static final String JDBC_PROP_FILE_ENV = "VOLTDB_JDBC_PROPERTIES";
public static final String JDBC_PROP_FILE_PROP = "voltdb.jdbcproperties";
public static final String DEFAULT_PROP_FILENAME = "voltdb.properties";
//Driver URL prefix.
private static final String URL_PREFIX = "jdbc:voltdb:";
static final String SSL_PROP= "ssl";
static final String TRUSTSTORE_CONFIG_PROP = "truststore";
static final String TRUSTSTORE_PASSWORD_PROP = "truststorepassword";
// Static so it's unit-testable, yes, lazy me
static String[] getServersFromURL(String url) {
// get everything between the prefix and the ?
String prefix = URL_PREFIX + "//";
int end = url.length();
if (url.indexOf("?") > 0) {
end = url.indexOf("?");
}
String servstring = url.substring(prefix.length(), end);
return servstring.split(",");
}
static Map getPropsFromURL(String url) {
Map results = new HashMap();
if (url.indexOf("?") > 0) {
String propstring = url.substring(url.indexOf("?") + 1);
String[] props = propstring.split("&");
for (String prop : props) {
if (prop.indexOf("=") > 0) {
String[] comps = prop.split("=");
results.put(comps[0], comps[1]);
}
}
}
return results;
}
private static final int MAJOR_VERSION = 1;
private static final int MINOR_VERSION = 0;
static
{
try
{
DriverManager.registerDriver(new Driver());
}
catch (Exception e)
{}
}
public Driver() throws SQLException
{
// Required for Class.forName().newInstance()
}
@Override
public Connection connect(String url, Properties props) throws SQLException
{
if (acceptsURL(url))
{
try
{
// Properties favored order:
// 1) property file specified by env variable
// 2) property file specified by system property
// 3) property file with default name in same path as driver jar
// 4) Properties specified in the URL
// 5) Properties specified to getConnection() arg
//
Properties fileprops = tryToFindPropsFile();
// Copy the provided properties so we don't muck with
// the object the caller gave us.
Properties info = (Properties) props.clone();
String prefix = URL_PREFIX + "//";
if (!url.startsWith(prefix)) {
throw SQLError.get(SQLError.ILLEGAL_ARGUMENT);
}
// get the server strings
String[] servers = Driver.getServersFromURL(url);
// get the props from the URL
Map urlprops = Driver.getPropsFromURL(url);
for (Entry e : urlprops.entrySet()) {
// Favor the URL over the provided props
info.setProperty(e.getKey(), e.getValue());
}
// Favor the file-specified properties over the other props
for (Enumeration e = fileprops.propertyNames(); e.hasMoreElements();)
{
String key = (String) e.nextElement();
info.setProperty(key, fileprops.getProperty(key));
}
String user = "";
String password = "";
boolean heavyweight = false;
int maxoutstandingtxns = 0;
boolean reconnectOnConnectionLoss = false;
boolean enableSSL = false;
String truststorePath = null;
String truststorePassword = null;
for (Enumeration e = info.propertyNames(); e.hasMoreElements();)
{
String key = (String) e.nextElement();
String value = info.getProperty(key);
if (key.toLowerCase().equals("user"))
user = value;
else if (key.toLowerCase().equals("password"))
password = value;
else if (key.toLowerCase().equals("heavyweight"))
heavyweight = (value.toLowerCase().equals("true") || value.toLowerCase().equals("yes") ||
value.toLowerCase().equals("1"));
else if (key.toLowerCase().equals("maxoutstandingtxns"))
maxoutstandingtxns = Integer.parseInt(value);
else if ("autoreconnect".equals(key)) {
reconnectOnConnectionLoss = ("true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value) || "1".equals(value));
}
else if (key.toLowerCase().equals(SSL_PROP)) {
enableSSL = value.toLowerCase().equals("true");
}
else if (key.toLowerCase().equals(TRUSTSTORE_CONFIG_PROP)) {
if ((value != null) && value.trim().length() > 0) {
truststorePath = value.trim();
}
}
else if (key.toLowerCase().equals(TRUSTSTORE_PASSWORD_PROP)) {
truststorePassword = value;
}
// else - unknown; ignore
}
SSLConfiguration.SslConfig sslConfig = null;
if (enableSSL) {
sslConfig = new SSLConfiguration.SslConfig(null, null, truststorePath, truststorePassword);
}
// Return JDBC connection wrapper for the client
return new JDBC4Connection(JDBC4ClientConnectionPool.get(servers, user, password,
heavyweight, maxoutstandingtxns, reconnectOnConnectionLoss, sslConfig),
info);
} catch (Exception x) {
throw SQLError.get(x, SQLError.CONNECTION_UNSUCCESSFUL);
}
}
return null;
}
@Override
public boolean acceptsURL(String url) throws SQLException
{
return Pattern.compile("^jdbc:voltdb://.+", Pattern.CASE_INSENSITIVE).matcher(url).matches();
}
@Override
public int getMajorVersion()
{
return MAJOR_VERSION;
}
@Override
public int getMinorVersion()
{
return MINOR_VERSION;
}
@Override
public DriverPropertyInfo[] getPropertyInfo(String url, Properties loginProps) throws SQLException
{
return new DriverPropertyInfo[0];
}
@Override
public boolean jdbcCompliant()
{
return false;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException();
}
private Properties tryToFindPropsFile() {
Properties fileprops = new Properties();
String filename = null;
// Check the env first
filename = System.getenv(Driver.JDBC_PROP_FILE_ENV);
if (filename == null) {
filename = System.getProperty(Driver.JDBC_PROP_FILE_PROP);
}
if (filename == null) {
// see if we can find a file in the default location
URL pathToJar = this.getClass().getProtectionDomain()
.getCodeSource().getLocation();
String tmp = null;
try {
tmp = new File(pathToJar.toURI()).getParent() + File.separator + DEFAULT_PROP_FILENAME;
} catch (Exception e) {
tmp = null;
}
filename = tmp;
}
if (filename != null) {
File propfile = new File(filename);
if (propfile.exists() && propfile.isFile()) {
FileInputStream in = null;
try {
in = new FileInputStream(propfile);
fileprops.load(in);
}
catch (FileNotFoundException fnfe) {}
catch (IOException ioe) {}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {}
}
}
}
}
return fileprops;
}
}