blob: b1636e56d262cfaa3624e34d5733af557e34aa1b [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2009, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.ecommons.edb.core;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.apache.commons.dbcp2.ConnectionFactory;
import org.apache.commons.dbcp2.DriverConnectionFactory;
import org.apache.commons.dbcp2.PoolableConnection;
import org.apache.commons.dbcp2.PoolableConnectionFactory;
import org.apache.commons.dbcp2.PoolingDataSource;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.derby.jdbc.EmbeddedDriver;
import org.eclipse.statet.internal.ecommons.edb.core.Activator;
public class EmbeddedDB {
private static abstract class AbstractDB {
private final String dbLabel;
public AbstractDB(final String dbLabel) {
this.dbLabel= dbLabel;
}
public DataSource createConnectionPool(final String uri) throws CoreException {
// see also PoolingDriverExample of DBCP
final ConnectionFactory connectionFactory= createConnectionFactory(uri);
final PoolableConnectionFactory poolableFactory= new PoolableConnectionFactory(connectionFactory, null);
poolableFactory.setDefaultReadOnly(false);
poolableFactory.setDefaultAutoCommit(true);
final ObjectPool<PoolableConnection> connectionPool= new GenericObjectPool<>(poolableFactory);
poolableFactory.setPool(connectionPool);
return new PoolingDataSource<>(connectionPool);
}
public abstract ConnectionFactory createConnectionFactory(final String uri) throws CoreException;
public void shutdown(final String uri) throws CoreException {
}
protected StringBuilder createErrorMessage(final String driverName, final Driver driver,
final String uri, final String task) {
final StringBuilder message= new StringBuilder("An error occurred when " + task + " embedded DB");
message.append(" (" + this.dbLabel + " + DBCP)"); //$NON-NLS-1$ //$NON-NLS-2$
message.append("\n\tDB ConnectionURL=").append(uri); //$NON-NLS-1$
message.append("\n\tDriver Name=").append(driverName); //$NON-NLS-1$
if (driver != null) {
message.append(", Version=").append(driver.getMajorVersion()).append('.').append(driver.getMinorVersion()); //$NON-NLS-1$
}
return message;
}
@Override
public String toString() {
return this.dbLabel;
}
}
private static class DerbyDB extends AbstractDB {
private static String DERBY_HOME_PROP= "derby.system.home"; //$NON-NLS-1$
private static String DRIVER_NAME= "org.apache.derby.jdbc.EmbeddedDriver"; //$NON-NLS-1$
public DerbyDB() {
super("Derby"); //$NON-NLS-1$
}
@Override
public ConnectionFactory createConnectionFactory(final String uri) throws CoreException {
if (System.getProperty(DERBY_HOME_PROP) == null) {
final IPath location= Activator.getInstance().getStateLocation();
System.setProperty(DERBY_HOME_PROP, location.toOSString());
}
final String driverName= DRIVER_NAME;
final String dbUrl= "jdbc:derby:" + uri; //$NON-NLS-1$
final Properties info= new Properties();
info.setProperty("create", "true"); //$NON-NLS-1$ //$NON-NLS-2$
Driver driver= null;
try {
// driver= (Driver) Class.forName(driverName, true, EmbeddedDB.class.getClassLoader()).newInstance();
driver= new EmbeddedDriver();
final Connection connection= driver.connect(dbUrl, info);
connection.close();
return new DriverConnectionFactory(driver, "jdbc:derby:" + uri, null); //$NON-NLS-1$
}
catch (final Exception e) {
final StringBuilder message= createErrorMessage(driverName, driver, uri, "loading");
throw new CoreException(new Status(IStatus.ERROR, Activator.BUNDLE_ID, -1, message.toString(), e));
}
}
@Override
public void shutdown(final String uri) throws CoreException {
if (System.getProperty(DERBY_HOME_PROP) == null) {
return;
}
final String driverName= DRIVER_NAME;
final String dbUrl= "jdbc:derby:" + uri + ";shutdown=true"; //$NON-NLS-1$ //$NON-NLS-2$
Driver driver= null;
try {
// driver= (Driver) Class.forName(driverName, true, EmbeddedDB.class.getClassLoader()).newInstance();
driver= new EmbeddedDriver();
final Connection connection= driver.connect(dbUrl, null);
connection.close();
}
catch (final Exception e) {
if (e instanceof SQLException && "08006".equals(((SQLException) e).getSQLState())) { //$NON-NLS-1$
return;
}
final StringBuilder message= createErrorMessage(driverName, driver, uri, "closing");
throw new CoreException(new Status(IStatus.ERROR, Activator.BUNDLE_ID, -1, message.toString(), e));
}
}
}
private static final AbstractDB db= new DerbyDB();
public static DataSource createConnectionPool(final String uri) throws CoreException {
return db.createConnectionPool(uri);
}
public static ConnectionFactory createConnectionFactory(final String uri) throws CoreException {
return db.createConnectionFactory(uri);
}
public static void shutdown(final String uri) throws CoreException {
db.shutdown(uri);
}
}