package org.apache.torque;
/*
* 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.
*/
import java.sql.Connection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import junit.framework.TestCase;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.torque.criteria.Criteria;
import org.apache.torque.dsfactory.AbstractDataSourceFactory;
import org.apache.torque.dsfactory.DataSourceFactory;
import org.apache.torque.dsfactory.JndiDataSourceFactory;
import org.apache.torque.test.peer.BookPeer;
/**
* Test for configuration using JNDI. The test assumes that we have a
* non-jndi configuration, and creates the data source configuration from it.
* It is tested whether we can bind a data source manually into jndi and
* retrieve it in Torque, and also it is tested whether we can bind a
* data source using Torque.
* Note: This test does not extend BaseRuntimeTestCase as we do not want Torque
* to be initialized.
*
* @author <a href="mailto:fischer@seitenbau.de">Thomas Fischer</a>
* @version $Id $
*/
public class JndiConfigurationTest extends TestCase
{
/**
* The subcontext where the data source is bound.
*/
protected static final String JNDI_SUBCONTEXT = "jdbc";
/**
* the full jndi path to the data source.
*/
protected static final String JNDI_PATH
= JNDI_SUBCONTEXT + "/" + "jndiTestDataSource";
public void setUp()
{
// super.setUp() initializes torque, but here we want to
// do that ourselves
}
/**
* Tests whether our home-made Data Source works.
* @throws Exception if the test fails.
*/
public void testDataSource() throws Exception
{
BasicDataSource dataSource = null;
try
{
dataSource = getDataSource();
dataSourceConnect(dataSource);
}
finally
{
if (dataSource != null)
{
dataSource.close();
}
}
}
/**
* Binds a DataSource to the jndi and checks that we have successfully
* bound it. Then Torque is configured to lookup the DataSource in jndi,
* and it is checked if Torque can read from the database. Finally,
* the DataSource is closed and unbound.
* @throws Exception if the test fails
*/
public void testExternalBindTorqueLookup() throws Exception
{
// compose the correct configuration
Configuration torqueConfiguration = getTorqueConfiguraton();
String defaultDatabase = getDefaultDatabase(torqueConfiguration);
// remove the dsfactory configuration from the configuration
{
Configuration dsfactoryConfiguration = torqueConfiguration.subset(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase);
dsfactoryConfiguration.clear();
}
// add the jndi configuration to the configuration
torqueConfiguration.setProperty(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ DataSourceFactory.FACTORY_KEY,
JndiDataSourceFactory.class.getName());
torqueConfiguration.setProperty(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ JndiDataSourceFactory.JNDI_KEY + "."
+ JndiDataSourceFactory.PATH_KEY,
JNDI_PATH);
torqueConfiguration.setProperty(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ JndiDataSourceFactory.JNDI_KEY + "."
+ Context.INITIAL_CONTEXT_FACTORY,
org.apache.naming.java.javaURLContextFactory.class.getName());
//System.out.println("Configuration for testExternalBindTorqueLookup:");
//debugConfiguration(torqueConfiguration);
//System.out.println();
try
{
// bind datasource and check bind.
bindDataSource();
BasicDataSource dataSource = retrieveDataSource();
dataSourceConnect(dataSource);
if (Torque.isInit())
{
Torque.shutdown();
}
// initialize torque with the created configuration
// and check that we can connect to the database.
try
{
Torque.init(torqueConfiguration);
torqueConnect();
}
finally
{
Torque.shutdown();
}
}
finally
{
unbindDataSource();
}
}
/**
* Binds a DataSource to the jndi and checks that we have successfully
* bound it. Then Torque is configured to lookup the DataSource in jndi,
* and it is checked if Torque can read from the database. Finally,
* the DataSource is closed and unbound.
* @throws Exception if the test fails
*/
public void testTorqueBindTorqueLookup() throws Exception
{
// compose the correct configuration
Configuration torqueConfiguration = getTorqueConfiguraton();
String defaultDatabase = getDefaultDatabase(torqueConfiguration);
// add the jndi configuration to the configuration
torqueConfiguration.setProperty(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ DataSourceFactory.FACTORY_KEY,
JndiDataSourceFactory.class.getName());
torqueConfiguration.setProperty(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ JndiDataSourceFactory.JNDI_KEY + "."
+ JndiDataSourceFactory.PATH_KEY,
JNDI_PATH);
torqueConfiguration.setProperty(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ JndiDataSourceFactory.JNDI_KEY + "."
+ Context.INITIAL_CONTEXT_FACTORY,
org.apache.naming.java.javaURLContextFactory.class.getName());
// add the datasource configuration
torqueConfiguration.setProperty(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ JndiDataSourceFactory.DATASOURCE_KEY + "."
+ JndiDataSourceFactory.CLASSNAME_KEY,
BasicDataSource.class.getName());
{
Map tempStore = new HashMap();
Configuration connectionConfiguration
= torqueConfiguration.subset(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ AbstractDataSourceFactory.CONNECTION_KEY);
for (Iterator keyIt = connectionConfiguration.getKeys();
keyIt.hasNext();)
{
String key = (String) keyIt.next();
String value = connectionConfiguration.getString(key);
if ("user".equals(key))
{
// setUser() in SharedPoolDataSouce corresponds to
// setUsername() in BasicDataSourceFactory
key = "username";
}
else if ("driver".equals(key))
{
// setDriver() in SharedPoolDataSouce corresponds to
// setDriverClassName() in BasicDataSourceFactory
key = "driverClassName";
}
tempStore.put(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ JndiDataSourceFactory.DATASOURCE_KEY + "."
+ key,
value);
}
// add the new keys
for (Iterator keyIt = tempStore.keySet().iterator();
keyIt.hasNext(); )
{
String key = (String) keyIt.next();
String value = (String) tempStore.get(key);
torqueConfiguration.setProperty(key, value);
}
// remove the configuration for the original datasource
connectionConfiguration.clear();
Configuration poolConfiguration
= torqueConfiguration.subset(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ AbstractDataSourceFactory.POOL_KEY);
poolConfiguration.clear();
}
//System.out.println("Configuration for testTorqueBindTorqueLookup:");
//debugConfiguration(torqueConfiguration);
//System.out.println();
try
{
// initialize torque with the created configuration
// and check that we can connect to the database.
try
{
Torque.init(torqueConfiguration);
torqueConnect();
}
finally
{
Torque.shutdown();
}
}
finally
{
unbindDataSource();
}
}
/**
* creates and binds a BasicDataSource into jndi.
* @throws Exception if DataSource creation or binding fails.
*/
protected void bindDataSource() throws Exception
{
BasicDataSource dataSource = getDataSource();
Context context = getInitialContext();
context.createSubcontext(JNDI_SUBCONTEXT);
context.bind(JNDI_PATH, dataSource);
}
/**
* Retrieves a BasicDataSource from jndi.
* @throws Exception if the jndi lookup fails or no DataSource is bound.
*/
protected BasicDataSource retrieveDataSource() throws Exception
{
Context context = getInitialContext();
BasicDataSource dataSource
= (BasicDataSource) context.lookup(JNDI_PATH);
if (dataSource == null)
{
fail("DataSource should not be null");
}
return dataSource;
}
/**
* unbinds and closes the BasicDataSource in jndi.
* @throws Exception if creation or binfding fails.
*/
protected void unbindDataSource() throws Exception
{
Context context = getInitialContext();
BasicDataSource dataSource
= (BasicDataSource) context.lookup(JNDI_PATH);
try
{
if (dataSource != null)
{
dataSource.close();
}
}
finally
{
context.unbind(JNDI_PATH);
}
}
/**
* Creates a Data Source from the Torque configuration without using Torque.
* @return a SharedPoolDataSource source.
* @throws Exception if we cannot create a Data source.
*/
protected BasicDataSource getDataSource() throws Exception
{
Configuration torqueConfiguration = getTorqueConfiguraton();
String defaultDatabase = getDefaultDatabase(torqueConfiguration);
Configuration dsfactoryConfiguration = torqueConfiguration.subset(
Torque.TORQUE_KEY + "."
+ DataSourceFactory.DSFACTORY_KEY + "."
+ defaultDatabase + "."
+ AbstractDataSourceFactory.CONNECTION_KEY);
BasicDataSource dataSource = new BasicDataSource();
for (Iterator i = dsfactoryConfiguration.getKeys(); i.hasNext();)
{
String key = (String) i.next();
String stringValue = dsfactoryConfiguration.getString(key);
if ("user".equals(key))
{
// setUser() in SharedPoolDataSouce corresponds to
// setUsername() in BasicDataSourceFactory
key = "username";
}
else if ("driver".equals(key))
{
// setDriver() in SharedPoolDataSouce corresponds to
// setDriverClassName() in BasicDataSourceFactory
key = "driverClassName";
}
Class propertyType =
PropertyUtils.getPropertyType(dataSource, key);
Object value =
ConvertUtils.convert(stringValue, propertyType);
PropertyUtils.setSimpleProperty(dataSource, key, value);
}
return dataSource;
}
/**
* checks whether we can retrieve a connection from a DataSource.
* @throws Exception if no connection can be established.
*/
protected void dataSourceConnect(DataSource dataSource) throws Exception
{
Connection connection = null;
try
{
connection = dataSource.getConnection();
connection.close();
connection = null;
}
finally
{
if (connection != null)
{
connection.close();
}
}
}
/**
* checks whether we can connect to the database via Torque.
* @throws Exception if no connection can be established.
*/
protected void torqueConnect() throws Exception
{
Connection connection = null;
try
{
connection = Torque.getConnection();
BookPeer.doSelect(new Criteria(), connection);
connection.close();
connection = null;
}
finally
{
if (connection != null)
{
connection.close();
}
}
}
/**
* Retrieves (or creates if it does not exist) an InitialContext.
* @return the InitialContext.
* @throws NamingException if the InitialContext cannot be retrieved
* or created.
*/
protected InitialContext getInitialContext() throws NamingException
{
Hashtable environment = new Hashtable();
environment.put(
Context.INITIAL_CONTEXT_FACTORY,
org.apache.naming.java.javaURLContextFactory.class.getName());
InitialContext context = new InitialContext(environment);
return context;
}
/**
* Retrieves the path for Torque's configuration from the System Properties,
* loads the configuration and returns it.
* @return Torque's configuration.
* @throws ConfigurationException if the configuration cannot be loaded.
*/
protected static Configuration getTorqueConfiguraton()
throws ConfigurationException
{
Configuration configuration = new PropertiesConfiguration(
System.getProperty(
BaseDatabaseTestCase.CONFIG_FILE_SYSTEM_PROPERTY));
return configuration;
}
/**
* extraxts the default Database out of Torque's configuration.
* @param torqueConfiguration the Torque configuration
* @return the default Data Source.
*/
protected static String getDefaultDatabase(
Configuration torqueConfiguration)
{
String defaultDatabase = torqueConfiguration.getString(
Torque.TORQUE_KEY + "."
+ Torque.DATABASE_KEY + "."
+ Torque.DEFAULT_KEY);
return defaultDatabase;
}
/**
* Prints the contents of the configuration to System.out
* @param configuration the configuration to be debugged.
*/
public static void debugConfiguration(Configuration configuration)
{
for (Iterator dsKeyIt = configuration.getKeys();
dsKeyIt.hasNext(); )
{
String key = (String) dsKeyIt.next();
System.out.println(key + " = " + configuration.getString(key));
}
}
}