/*
* Copyright 2006-2012 The Scriptella Project Team.
*
* 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
*
* 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 scriptella.driver.jndi;
import scriptella.AbstractTestCase;
import scriptella.configuration.MockConnectionEl;
import scriptella.jdbc.JdbcConnection;
import scriptella.jdbc.JdbcException;
import scriptella.spi.ConnectionParameters;
import scriptella.spi.MockDriverContext;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;
import javax.sql.DataSource;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.logging.Logger;
/**
* Tests JNDI driver class.
*
* @author Fyodor Kupolov
* @version 1.0
*/
public class JNDIDriverTest extends AbstractTestCase {
/**
* Tests the driver by emulating the JNDI environment with a JNDI-bound datasource.
*/
public void testGetConnection() throws NamingException {
//Just to initialize HSLQB driver class
Logger.getAnonymousLogger().fine("Initializing " + new scriptella.driver.hsqldb.Driver());
//Preparing the environment
Map<String, String> env = new HashMap<String, String>();
//Setting up a test JNDI factory
env.put(Context.INITIAL_CONTEXT_FACTORY, CtxFactory.class.getName());
CtxFactory.jndiName = "datasourceName";
CtxFactory.connections = 0;
CtxFactory.lookups = 0;
ConnectionParameters params = new ConnectionParameters(new MockConnectionEl(env, CtxFactory.jndiName), MockDriverContext.INSTANCE);
Driver drv = new Driver();
JdbcConnection con1 = drv.connect(params);
con1.close();
assertNotNull(con1);
JdbcConnection con2 = drv.connect(params);
con2.close();
assertNotNull(con2);
assertTrue("con1 and con2 must be different connections", con1 != con2);
//lookup and getConnection called 2 times
assertEquals("Illegal number of lookups", 2, CtxFactory.lookups);
assertEquals("Illegal number of created connections", 2, CtxFactory.connections);
}
/**
* Tests if validation of connection parameters is performed.
* @throws SQLException
*/
public void testValidation() throws SQLException {
Driver drv = new Driver();
try {
drv.getConnection(null , null);
} catch (JdbcException e) {
//ok
}
}
/**
* Represents {@link InitialContextFactory} for JNDI and an {@link InvocationHandler} for
* emulating Context and Datasource simultaneously.
*/
public static class CtxFactory implements InitialContextFactory, InvocationHandler {
public static String jndiName;
public static int lookups;
public static int connections;
public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
return (Context) Proxy.newProxyInstance(getClass().getClassLoader(),
new Class<?>[]{Context.class, DataSource.class}, this);
}
/**
* This invoker supports 2 methods:
* {@link Context#lookup(String)} and {@link javax.sql.DataSource#getConnection()}
*
* @throws SQLException if db exception occurs
*/
public Object invoke(Object proxy, Method method, Object[] args) throws SQLException {
if ("lookup".equals(method.getName())) {
lookups++;
String name = (String) args[0];
if (!jndiName.equals(name)) {
fail("Expected " + jndiName + " JNDI name but was " + name);
}
return proxy;
} else if ("getConnection".equals(method.getName())) {
connections++;
return DriverManager.getConnection("jdbc:hsqldb:mem:jnditest", "sa", "");
} else {
throw new UnsupportedOperationException();
}
}
}
}