blob: 5f6e4d506627dac8488fc3bd6b2b7f3c239f4613 [file] [log] [blame]
/*
*
* Derby - Class org.apache.derbyTesting.junit.JDBCDataSource
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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
*
* http://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 org.apache.derbyTesting.junit;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import junit.framework.Assert;
/**
* Utility methods related to JDBC DataSource objects.
* J2EEDataSource exists to return XA and connection pooling data sources.
*
* @see J2EEDataSource
*/
public class JDBCDataSource {
/**
* Return a new DataSource corresponding to the current
* configuration. The getConnection() method will return
* a connection identical to TestConfiguration.openDefaultConnection().
*/
public static javax.sql.DataSource getDataSource()
{
return getDataSource(TestConfiguration.getCurrent(), (HashMap) null);
}
/**
* Return a new DataSource corresponding to the current
* configuration except that the database name is different.
*/
public static javax.sql.DataSource getDataSource(String dbName)
{
// default DataSource
javax.sql.DataSource ds = getDataSource();
// Override the database name
setBeanProperty(ds, "databaseName", dbName);
return ds;
}
/**
* Return a DataSource corresponding to one
* of the logical databases in the current configuration.
*/
public static javax.sql.DataSource
getDataSourceLogical(String logicalDatabasename)
{
// default DataSource
javax.sql.DataSource ds = getDataSource();
TestConfiguration current = TestConfiguration.getCurrent();
String physicalName =
current.getPhysicalDatabaseName(logicalDatabasename);
// Override the database name
setBeanProperty(ds, "databaseName", physicalName);
return ds;
}
/**
* Create a new DataSource object setup from the passed in TestConfiguration.
* The getConnection() method will return a connection identical to
* TestConfiguration.openDefaultConnection().
*/
static javax.sql.DataSource getDataSource(TestConfiguration config,
HashMap beanProperties)
{
return (javax.sql.DataSource) getDataSource(config,
beanProperties, config.getJDBCClient().getDataSourceClassName());
}
/**
* Create a new DataSource object setup from the passed in
* TestConfiguration using the received properties and data
* source class name.
*/
static Object getDataSource(TestConfiguration config,
HashMap beanProperties, String dsClassName)
{
if (beanProperties == null)
beanProperties = getDataSourceProperties(config);
return getDataSourceObject(dsClassName,
beanProperties);
}
/**
* Create a HashMap with the set of Derby DataSource
* Java bean properties corresponding to the configuration.
*/
static HashMap<String, Object> getDataSourceProperties(TestConfiguration config)
{
HashMap<String, Object> beanProperties = new HashMap<String, Object>();
if (!config.getJDBCClient().isEmbedded()) {
beanProperties.put("serverName", config.getHostName());
beanProperties.put("portNumber", config.getPort());
}
beanProperties.put("databaseName", config.getDefaultDatabaseName());
beanProperties.put("user", config.getUserName());
beanProperties.put("password", config.getUserPassword());
String attributes = config.getConnectionAttributesString();
if (attributes != null) {
beanProperties.put("connectionAttributes", attributes);
}
return beanProperties;
}
/**
* Return a DataSource object of the passed in type
* configured with the passed in Java bean properties.
* This will actually work with any object that has Java bean
* setter methods.
* <BR>
* If a thread context class loader exists then it is used
* to try and load the class.
*/
static javax.sql.DataSource getDataSourceObject(String classname, HashMap beanProperties)
{
ClassLoader contextLoader = AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
try {
javax.sql.DataSource ds = null;
if (contextLoader != null)
{
try {
Class<?> clazz = Class.forName(classname, true, contextLoader);
ds = (javax.sql.DataSource) clazz.getConstructor().newInstance();
} catch (Exception e) {
// context loader may not be correctly hooked up
// with parent, try without it.
}
}
if (ds == null)
{
Class<?> clazz = Class.forName(classname);
ds = (javax.sql.DataSource) clazz.getConstructor().newInstance();
}
for (Iterator i = beanProperties.keySet().iterator();
i.hasNext(); )
{
String property = (String) i.next();
Object value = beanProperties.get(property);
setBeanProperty(ds, property, value);
}
if ( !BaseTestCase.isJ9Platform() && !BaseTestCase.isCVM() )
{
ds.setLoginTimeout( TestConfiguration.getCurrent().getLoginTimeout() );
}
return ds;
} catch (Exception e) {
BaseTestCase.printStackTrace( e );
BaseTestCase.fail("unexpected error: " + e.getMessage(), e);
return null;
}
}
/**
* Set a bean property for a data source. This code can be used
* on any data source type.
* @param ds DataSource to have property set
* @param property name of property.
* @param value Value, type is derived from value's class.
*/
public static void setBeanProperty(Object ds, String property, Object value)
{
String setterName = getSetterName(property);
// Base the type of the setter method from the value's class.
Class clazz = value.getClass();
if (Integer.class.equals(clazz))
clazz = Integer.TYPE;
else if (Boolean.class.equals(clazz))
clazz = Boolean.TYPE;
else if (Short.class.equals(clazz))
clazz = Short.TYPE;
try {
Method setter = ds.getClass().getMethod(setterName,
new Class[] {clazz});
setter.invoke(ds, new Object[] {value});
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
/**
* Get a bean property for a data source. This code can be used
* on any data source type.
* @param ds DataSource to fetch property from
* @param property name of property.
*/
public static Object getBeanProperty(Object ds, String property)
throws Exception
{
String getterName = getGetterName(property);
Method getter = ds.getClass().getMethod(getterName,
new Class[0]);
return getter.invoke(ds, new Object[0]);
}
/**
* Clear a String Java bean property by setting it to null.
* @param ds DataSource to have property cleared
* @param property name of property.
*/
public static void clearStringBeanProperty(Object ds, String property)
{
String setterName = getSetterName(property);
try {
Method setter = ds.getClass().getMethod(setterName,
new Class[] {String.class});
setter.invoke(ds, new Object[] {null});
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
private static String getSetterName(String attribute) {
return "set" + Character.toUpperCase(attribute.charAt(0))
+ attribute.substring(1);
}
private static String getGetterName(String attribute) {
return "get" + Character.toUpperCase(attribute.charAt(0))
+ attribute.substring(1);
}
/**
* Shutdown the database described by this data source.
* The shutdownDatabase property is cleared by this method.
*/
public static void shutdownDatabase(javax.sql.DataSource ds)
{
setBeanProperty(ds, "shutdownDatabase", "shutdown");
try {
ds.getConnection();
Assert.fail("Database failed to shut down");
} catch (SQLException e) {
BaseJDBCTestCase.assertSQLState("Database shutdown", "08006", e);
} finally {
clearStringBeanProperty(ds, "shutdownDatabase");
}
}
/**
* Shutdown the engine described by this data source.
* The shutdownDatabase property is cleared by this method.
*/
public static void shutEngine(javax.sql.DataSource ds) throws SQLException {
setBeanProperty(ds, "shutdownDatabase", "shutdown");
JDBCDataSource.setBeanProperty(ds, "databaseName", "");
try {
ds.getConnection();
Assert.fail("Engine failed to shut down");
} catch (SQLException e) {
BaseJDBCTestCase.assertSQLState("Engine shutdown", "XJ015", e);
} finally {
clearStringBeanProperty(ds, "shutdownDatabase");
}
}
}