io.micronaut.jdbc.JdbcDatabaseManager Maven / Gradle / Ivy
Show all versions of micronaut-jdbc Show documentation
/*
* Copyright 2017-2020 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.jdbc;
import io.micronaut.core.reflect.ClassUtils;
import io.micronaut.core.util.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
/**
* Stores information on popular JDBC drivers.
*
* @author James Kleeh
* @since 1.0
*/
public class JdbcDatabaseManager {
private static List databases = new ArrayList<>(16);
static {
databases.add(new EmbeddedJdbcDatabase("org.h2.Driver", "h2", "jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"));
databases.add(new EmbeddedJdbcDatabase("org.apache.derby.jdbc.EmbeddedDriver", "SELECT 1 FROM SYSIBM.SYSDUMMY1", new String[]{"derby"}, "jdbc:derby:memory:%s;create=true"));
databases.add(new EmbeddedJdbcDatabase("org.hsqldb.jdbc.JDBCDriver", "select 1 from INFORMATION_SCHEMA.SYSTEM_USERS", new String[]{"hsqldb"}, "jdbc:hsqldb:mem:%s"));
databases.add(new JdbcDatabase("com.mysql.cj.jdbc.Driver", "mysql"));
databases.add(new JdbcDatabase("oracle.jdbc.OracleDriver", "SELECT 1 FROM DUAL", new String[]{"oracle"}));
databases.add(new JdbcDatabase("org.postgresql.Driver", "postgresql"));
databases.add(new JdbcDatabase("com.microsoft.sqlserver.jdbc.SQLServerDriver", "sqlserver"));
databases.add(new JdbcDatabase("org.sqlite.JDBC", "sqlite"));
databases.add(new JdbcDatabase("org.mariadb.jdbc.Driver", "mariadb"));
databases.add(new JdbcDatabase("com.google.appengine.api.rdbms.AppEngineDriver", "gae"));
databases.add(new JdbcDatabase("net.sourceforge.jtds.jdbc.Driver", "jtds"));
databases.add(new JdbcDatabase("org.firebirdsql.jdbc.FBDriver", "SELECT 1 FROM RDB$DATABASE", new String[]{"firebirdsql"}));
databases.add(new JdbcDatabase("com.ibm.db2.jcc.DB2Driver", "SELECT 1 FROM SYSIBM.SYSDUMMY1", new String[]{"db2"}));
databases.add(new JdbcDatabase("com.ibm.as400.access.AS400JDBCDriver", "SELECT 1 FROM SYSIBM.SYSDUMMY1", new String[]{"as400"}));
databases.add(new JdbcDatabase("com.teradata.jdbc.TeraDriver", "teradata"));
databases.add(new JdbcDatabase("com.informix.jdbc.IfxDriver", "select count(*) from systables", new String[]{"informix"}));
}
/**
* Searches defined database where the URL prefix matches one of the prefixes defined in a {@link JdbcDatabase}.
* The prefix is determined by:
*
* jdbc:prefix:...
*
* @param jdbcUrl The connection URL
* @return An optional {@link JdbcDatabase}
*/
@SuppressWarnings("MagicNumber")
public static Optional findDatabase(String jdbcUrl) {
if (StringUtils.isNotEmpty(jdbcUrl)) {
if (!jdbcUrl.startsWith("jdbc")) {
throw new IllegalArgumentException("Invalid JDBC URL [" + jdbcUrl + "]. JDBC URLs must start with 'jdbc'.");
}
String partialUrl = jdbcUrl.substring(5);
String prefix = partialUrl.substring(0, partialUrl.indexOf(':')).toLowerCase();
return databases.stream().filter(db -> db.containsPrefix(prefix)).findFirst();
}
return Optional.empty();
}
/**
* Searches the provided classloader for an embedded database driver.
*
* @param classLoader The classloader to search
* @return An optional {@link EmbeddedJdbcDatabase}
*/
public static Optional get(ClassLoader classLoader) {
return databases
.stream()
.filter(JdbcDatabase::isEmbedded)
.map(EmbeddedJdbcDatabase.class::cast)
.filter(embeddedDatabase -> ClassUtils.isPresent(embeddedDatabase.getDriverClassName(), classLoader))
.findFirst();
}
/**
* Searches embedded databases where the driver matches the argument.
*
* @param driverClassName The driver class name to search on
* @return True if the driver matches an embedded database type
*/
public static boolean isEmbedded(String driverClassName) {
return databases
.stream()
.filter(JdbcDatabase::isEmbedded)
.anyMatch(db -> db.driverClassName.equals(driverClassName));
}
/**
* Provides the required information in order to connect toa JDBC database, including the necessary driver and
* validation query.
*/
public static class JdbcDatabase {
private String driverClassName;
private String validationQuery;
private Collection urlPrefixes;
/**
* @param driverClassName The jdbc driver class name
* @param validationQuery The validation query
* @param urlPrefixes The url prefixes
*/
JdbcDatabase(String driverClassName, String validationQuery, String[] urlPrefixes) {
this.driverClassName = driverClassName;
this.urlPrefixes = Arrays.asList(urlPrefixes);
this.validationQuery = validationQuery;
}
/**
* @param driverClassName The jdbc driver class name
* @param urlPrefixes The url prefixes
*/
JdbcDatabase(String driverClassName, String[] urlPrefixes) {
this(driverClassName, "SELECT 1", urlPrefixes);
}
/**
* @param driverClassName The jdbc driver class name
* @param urlPrefix The url prefix
*/
JdbcDatabase(String driverClassName, String urlPrefix) {
this(driverClassName, "SELECT 1", new String[]{urlPrefix});
}
/**
* @return Whether the database is embedded
*/
protected boolean isEmbedded() {
return Boolean.FALSE;
}
/**
* @return The name of the driver class
*/
public String getDriverClassName() {
return driverClassName;
}
/**
* @return The query to run to the validate the connection
*/
public String getValidationQuery() {
return validationQuery;
}
/**
* @param prefix The prefix to check
* @return Whether the url prefixes contain the prefix
*/
public boolean containsPrefix(String prefix) {
return urlPrefixes.contains(prefix);
}
}
/**
* Extends {@link JdbcDatabase} with additional defaults for the use of embedded databases such as H2.
*/
public static class EmbeddedJdbcDatabase extends JdbcDatabase {
private String defaultUrl;
private String defaultName = "devDb";
/**
* @param driverClassName The jdbc driver class name
* @param validationQuery The validation query
* @param urlPrefixes The url prefixes
* @param defaultUrl The default url
*/
EmbeddedJdbcDatabase(String driverClassName, String validationQuery, String[] urlPrefixes, String defaultUrl) {
super(driverClassName, validationQuery, urlPrefixes);
this.defaultUrl = defaultUrl;
}
/**
* @param driverClassName The jdbc driver class name
* @param urlPrefixes The url prefixes
* @param defaultUrl The default url
*/
EmbeddedJdbcDatabase(String driverClassName, String[] urlPrefixes, String defaultUrl) {
super(driverClassName, urlPrefixes);
this.defaultUrl = defaultUrl;
}
/**
* @param driverClassName The jdbc driver class name
* @param urlPrefix The url prefix
* @param defaultUrl The default url
*/
EmbeddedJdbcDatabase(String driverClassName, String urlPrefix, String defaultUrl) {
super(driverClassName, urlPrefix);
this.defaultUrl = defaultUrl;
}
/**
* Obtain an embedded database URL for the given database name.
*
* @param databaseName The database name
* @return The URL
*/
public String getUrl(String databaseName) {
if (databaseName == null) {
databaseName = defaultName;
}
return String.format(this.defaultUrl, databaseName);
}
@Override
protected boolean isEmbedded() {
return Boolean.TRUE;
}
}
}