org.h2.util.OsgiDataSourceFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of h2-mvstore Show documentation
Show all versions of h2-mvstore Show documentation
Fork of h2database to maintain Java 8 compatibility
The newest version!
/*
* Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (https://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.util;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Hashtable;
import java.util.Properties;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import javax.sql.XADataSource;
import org.h2.engine.Constants;
import org.h2.jdbcx.JdbcDataSource;
import org.osgi.framework.BundleContext;
import org.osgi.service.jdbc.DataSourceFactory;
/**
* This class implements the OSGi DataSourceFactory interface for the H2 JDBC
* driver. The following standard configuration properties are supported:
* {@link #JDBC_USER}, {@link #JDBC_PASSWORD}, {@link #JDBC_DESCRIPTION},
* {@link #JDBC_DATASOURCE_NAME}, {@link #JDBC_NETWORK_PROTOCOL},
* {@link #JDBC_URL}, {@link #JDBC_SERVER_NAME}, {@link #JDBC_PORT_NUMBER}. The
* following standard configuration properties are not supported:
* {@link #JDBC_ROLE_NAME}, {@link #JDBC_DATABASE_NAME},
* {@link #JDBC_INITIAL_POOL_SIZE}, {@link #JDBC_MAX_POOL_SIZE},
* {@link #JDBC_MIN_POOL_SIZE}, {@link #JDBC_MAX_IDLE_TIME},
* {@link #JDBC_MAX_STATEMENTS}, {@link #JDBC_PROPERTY_CYCLE}. Any other
* property will be treated as a H2 specific option. If the {@link #JDBC_URL}
* property is passed to any of the DataSource factories, the following
* properties will be ignored: {@link #JDBC_DATASOURCE_NAME},
* {@link #JDBC_NETWORK_PROTOCOL}, {@link #JDBC_SERVER_NAME},
* {@link #JDBC_PORT_NUMBER}.
*
* @author Per Otterstrom
*/
public class OsgiDataSourceFactory implements DataSourceFactory {
private final org.h2.Driver driver;
public OsgiDataSourceFactory(org.h2.Driver driver) {
this.driver = driver;
}
/**
* Creates a basic data source.
*
* @param properties the properties for the data source.
* @throws SQLException if unsupported properties are supplied, or if data
* source can not be created.
* @return a new data source.
*/
@Override
public DataSource createDataSource(Properties properties)
throws SQLException {
// Make copy of properties
Properties propertiesCopy = new Properties();
if (properties != null) {
propertiesCopy.putAll(properties);
}
// Verify that no unsupported standard options are used
rejectUnsupportedOptions(propertiesCopy);
// Standard pool properties in OSGi not applicable here
rejectPoolingOptions(propertiesCopy);
JdbcDataSource dataSource = new JdbcDataSource();
setupH2DataSource(dataSource, propertiesCopy);
return dataSource;
}
/**
* Creates a pooled data source.
*
* @param properties the properties for the data source.
* @throws SQLException if unsupported properties are supplied, or if data
* source can not be created.
* @return a new data source.
*/
@Override
public ConnectionPoolDataSource createConnectionPoolDataSource(
Properties properties) throws SQLException {
// Make copy of properties
Properties propertiesCopy = new Properties();
if (properties != null) {
propertiesCopy.putAll(properties);
}
// Verify that no unsupported standard options are used
rejectUnsupportedOptions(propertiesCopy);
// The integrated connection pool is H2 is not configurable
rejectPoolingOptions(propertiesCopy);
JdbcDataSource dataSource = new JdbcDataSource();
setupH2DataSource(dataSource, propertiesCopy);
return dataSource;
}
/**
* Creates a pooled XA data source.
*
* @param properties the properties for the data source.
* @throws SQLException if unsupported properties are supplied, or if data
* source can not be created.
* @return a new data source.
*/
@Override
public XADataSource createXADataSource(Properties properties)
throws SQLException {
// Make copy of properties
Properties propertiesCopy = new Properties();
if (properties != null) {
propertiesCopy.putAll(properties);
}
// Verify that no unsupported standard options are used
rejectUnsupportedOptions(propertiesCopy);
// The integrated connection pool is H2 is not configurable
rejectPoolingOptions(propertiesCopy);
JdbcDataSource dataSource = new JdbcDataSource();
setupH2DataSource(dataSource, propertiesCopy);
return dataSource;
}
/**
* Returns a driver. The H2 driver does not support any properties.
*
* @param properties must be null or empty list.
* @throws SQLException if any property is supplied.
* @return a driver.
*/
@Override
public java.sql.Driver createDriver(Properties properties)
throws SQLException {
if (properties != null && !properties.isEmpty()) {
// No properties supported
throw new SQLException();
}
return driver;
}
/**
* Checker method that will throw if any unsupported standard OSGi options
* is present.
*
* @param p the properties to check
* @throws SQLFeatureNotSupportedException if unsupported properties are
* present
*/
private static void rejectUnsupportedOptions(Properties p)
throws SQLFeatureNotSupportedException {
// Unsupported standard properties in OSGi
if (p.containsKey(DataSourceFactory.JDBC_ROLE_NAME)) {
throw new SQLFeatureNotSupportedException("The " +
DataSourceFactory.JDBC_ROLE_NAME +
" property is not supported by H2");
}
if (p.containsKey(DataSourceFactory.JDBC_DATASOURCE_NAME)) {
throw new SQLFeatureNotSupportedException("The " +
DataSourceFactory.JDBC_DATASOURCE_NAME +
" property is not supported by H2");
}
}
/**
* Applies common OSGi properties to a H2 data source. Non standard
* properties will be applied as H2 options.
*
* @param dataSource the data source to configure
* @param p the properties to apply to the data source
*/
private static void setupH2DataSource(JdbcDataSource dataSource,
Properties p) {
// Setting user and password
if (p.containsKey(DataSourceFactory.JDBC_USER)) {
dataSource.setUser((String) p.remove(DataSourceFactory.JDBC_USER));
}
if (p.containsKey(DataSourceFactory.JDBC_PASSWORD)) {
dataSource.setPassword((String) p
.remove(DataSourceFactory.JDBC_PASSWORD));
}
// Setting description
if (p.containsKey(DataSourceFactory.JDBC_DESCRIPTION)) {
dataSource.setDescription((String) p
.remove(DataSourceFactory.JDBC_DESCRIPTION));
}
// Setting URL
StringBuilder connectionUrl = new StringBuilder();
if (p.containsKey(DataSourceFactory.JDBC_URL)) {
// Use URL if specified
connectionUrl.append(p.remove(DataSourceFactory.JDBC_URL));
// Remove individual properties
p.remove(DataSourceFactory.JDBC_NETWORK_PROTOCOL);
p.remove(DataSourceFactory.JDBC_SERVER_NAME);
p.remove(DataSourceFactory.JDBC_PORT_NUMBER);
p.remove(DataSourceFactory.JDBC_DATABASE_NAME);
} else {
// Creating URL from individual properties
connectionUrl.append(Constants.START_URL);
// Set network protocol (tcp/ssl) or DB type (mem/file)
String protocol = "";
if (p.containsKey(DataSourceFactory.JDBC_NETWORK_PROTOCOL)) {
protocol = (String) p.remove(DataSourceFactory.JDBC_NETWORK_PROTOCOL);
connectionUrl.append(protocol).append(":");
}
// Host name and/or port
if (p.containsKey(DataSourceFactory.JDBC_SERVER_NAME)) {
connectionUrl.append("//").append(
p.remove(DataSourceFactory.JDBC_SERVER_NAME));
if (p.containsKey(DataSourceFactory.JDBC_PORT_NUMBER)) {
connectionUrl.append(":").append(
p.remove(DataSourceFactory.JDBC_PORT_NUMBER));
}
connectionUrl.append("/");
} else if (p.containsKey(
DataSourceFactory.JDBC_PORT_NUMBER)) {
// Assume local host if only port was set
connectionUrl
.append("//localhost:")
.append(p.remove(DataSourceFactory.JDBC_PORT_NUMBER))
.append("/");
} else if (protocol.equals("tcp") || protocol.equals("ssl")) {
// Assume local host if network protocol is set, but no host or
// port is set
connectionUrl.append("//localhost/");
}
// DB path and name
if (p.containsKey(DataSourceFactory.JDBC_DATABASE_NAME)) {
connectionUrl.append(
p.remove(DataSourceFactory.JDBC_DATABASE_NAME));
}
}
// Add remaining properties as options
for (Object option : p.keySet()) {
connectionUrl.append(";").append(option).append("=")
.append(p.get(option));
}
if (connectionUrl.length() > Constants.START_URL.length()) {
dataSource.setURL(connectionUrl.toString());
}
}
/**
* Checker method that will throw if any pooling related standard OSGi
* options are present.
*
* @param p the properties to check
* @throws SQLFeatureNotSupportedException if unsupported properties are
* present
*/
private static void rejectPoolingOptions(Properties p)
throws SQLFeatureNotSupportedException {
if (p.containsKey(DataSourceFactory.JDBC_INITIAL_POOL_SIZE) ||
p.containsKey(DataSourceFactory.JDBC_MAX_IDLE_TIME) ||
p.containsKey(DataSourceFactory.JDBC_MAX_POOL_SIZE) ||
p.containsKey(DataSourceFactory.JDBC_MAX_STATEMENTS) ||
p.containsKey(DataSourceFactory.JDBC_MIN_POOL_SIZE) ||
p.containsKey(DataSourceFactory.JDBC_PROPERTY_CYCLE)) {
throw new SQLFeatureNotSupportedException(
"Pooling properties are not supported by H2");
}
}
/**
* Register the H2 JDBC driver service.
*
* @param bundleContext the bundle context
* @param driver the driver
*/
static void registerService(BundleContext bundleContext,
org.h2.Driver driver) {
Hashtable properties = new Hashtable<>();
properties.put(
DataSourceFactory.OSGI_JDBC_DRIVER_CLASS,
org.h2.Driver.class.getName());
properties.put(
DataSourceFactory.OSGI_JDBC_DRIVER_NAME,
"H2 JDBC Driver");
properties.put(
DataSourceFactory.OSGI_JDBC_DRIVER_VERSION,
Constants.FULL_VERSION);
properties.put(DataSourceFactory.OSGI_JDBC_CAPABILITY, new String[] {
DataSourceFactory.OSGI_JDBC_CAPABILITY_DRIVER,
DataSourceFactory.OSGI_JDBC_CAPABILITY_DATASOURCE,
DataSourceFactory.OSGI_JDBC_CAPABILITY_CONNECTIONPOOLDATASOURCE,
DataSourceFactory.OSGI_JDBC_CAPABILITY_XADATASOURCE
});
bundleContext.registerService(
DataSourceFactory.class.getName(),
new OsgiDataSourceFactory(driver), properties);
}
}