blob: 1f4b605d9e43bf69291efd1c0303fbd02e802649 [file] [log] [blame]
/*
* 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.openjpa.conf;
import java.util.Properties;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceException;
import org.apache.openjpa.persistence.OpenJPAPersistence;
import org.apache.openjpa.util.UserException;
import junit.framework.TestCase;
/**
* Verifies appropriate exception is thrown when an incorrect protocol or
* sub-protocol is specified in the JDBC URL. Per the JDBC specification, the
* Driver should return a null connection upon getConnection() when a bad driver
* is specified on the URL. OpenJPA must be able to handle this condition and
* return an appropriate message.
*
* OpenJPA JIRA: {@link http://issues.apache.org/jira/browse/OPENJPA-656}
*
* @author Jeremy Bauer
* @author Pinaki Poddar
*
*/
public class TestBadJdbcUrl extends TestCase {
public static final String GOOD_URL =
"jdbc:derby:target/database/openjpa-derby-database;create=true";
public static final String GOOD_DRIVER =
"org.apache.derby.jdbc.EmbeddedDriver";
public static final String GOOD_DATASOURCE =
"org.apache.commons.dbcp2.BasicDataSource";
public static final String BAD_DRIVER = "bad.driver";
public static final String BAD_URL_PROTOCOL = "bad.url.protocol";
public static final String BAD_URL_SUBPROTOCOL = "bad.url.sub.protocol";
public static final String BAD_CONN_PROPS =
"connectionUrl=bad,connectionDriver=bad";
/*
* Test specifying URL with bad protocol but a valid Driver.
*/
public void testBadUrlProtocolValueWithValidDriverClass() {
Properties p = new Properties();
p.put("openjpa.ConnectionDriverName", GOOD_DRIVER);
p.put("openjpa.ConnectionURL", BAD_URL_PROTOCOL);
verifyConnectException(p, PersistenceException.class,
UserException.class, GOOD_DRIVER, BAD_URL_PROTOCOL);
}
/*
* Test specifying URL with bad protocol but a valid DataSource.
*/
public void testBadUrlProtocolValueWithValidDataSource() {
Properties p = new Properties();
p.put("openjpa.ConnectionDriverName", GOOD_DATASOURCE);
p.put("openjpa.ConnectionURL", BAD_URL_PROTOCOL);
p.put("openjpa.ConnectionProperties", BAD_CONN_PROPS);
verifyConnectException(p, PersistenceException.class,
null, (String[])null);
}
/*
* Test specifying URL with bad sub-protocol but a valid Driver.
*/
public void testBadUrlSubprotocolValueWithValidDriverClass() {
Properties p = new Properties();
p.put("openjpa.ConnectionDriverName", GOOD_DRIVER);
p.put("openjpa.ConnectionURL", BAD_URL_SUBPROTOCOL);
verifyConnectException(p, PersistenceException.class,
UserException.class, GOOD_DRIVER, BAD_URL_SUBPROTOCOL);
}
/*
* Test specifying URL with bad sub-protocol but a valid Driver.
*/
public void testBadUrlSubprotocolValueWithValidDataSource() {
Properties p = new Properties();
p.put("openjpa.ConnectionDriverName", GOOD_DRIVER);
p.put("openjpa.ConnectionURL", BAD_URL_SUBPROTOCOL);
verifyConnectException(p, PersistenceException.class,
UserException.class, GOOD_DRIVER, BAD_URL_SUBPROTOCOL);
}
/*
* Test specifying Valid URL with an invalid Driver.
*/
public void testValidUrlWithInvalidDriver() {
Properties p = new Properties();
p.put("openjpa.ConnectionDriverName", BAD_DRIVER);
p.put("openjpa.ConnectionURL", GOOD_URL);
verifyConnectException(p, PersistenceException.class,
UserException.class, GOOD_URL, BAD_DRIVER);
}
/**
* Attempts to connect with given properties and analyze exception for the
* existence of given target exception and error message strings.
*
* @param props
* the properties to initialize the persistence unit
* @param target
* the type expected exception to be raised.
* @param nested
* the type expected nested exception. null implies not to look
* for any.
* @param keys
* the strings that must occur in the exception message.
*/
private void verifyConnectException(Properties props, Class targetType,
Class nestedType, String... keys) {
EntityManagerFactory emf = null;
EntityManager em = null;
try {
emf = Persistence.createEntityManagerFactory("test", props);
em = emf.createEntityManager();
OpenJPAPersistence.cast(em).getConnection();
fail("Should have caught a " + targetType.getName());
} catch (Throwable t) {
assertException(t, targetType, nestedType);
assertMessage(t, keys);
} finally {
if (em != null)
em.close();
if (emf != null)
emf.close();
}
}
/**
* Asserts that the given targetType is assignable from actual. Asserts that
* the nestedType is a nested within the given actual Throwable
*
* @param actual
* @param targetType
* @param nestedType
*/
void assertException(final Throwable actual, Class targetType,
Class nestedTargetType) {
if (targetType == null)
return;
assertNotNull(actual);
Class actualType = actual.getClass();
if (!targetType.isAssignableFrom(actualType)) {
fail(targetType.getName() + " is not assignable from "
+ actualType.getName());
}
if (nestedTargetType != null) {
Throwable nested = actual.getCause();
Class nestedType = (nested == null) ? null : nested.getClass();
while (nestedType != null) {
if (nestedType.isAssignableFrom(nestedTargetType)) {
return;
} else {
Throwable next = nested.getCause();
if (next == null || next == nested)
break;
nestedType = next.getClass();
nested = next;
}
}
fail("No nested type " + nestedTargetType + " in " + actual);
}
}
/**
* Assert that each of given keys are present in the message of the given
* Throwable.
*/
void assertMessage(Throwable actual, String... keys) {
if (actual == null || keys == null)
return;
String message = actual.getMessage();
for (String key : keys) {
assertTrue(key + " is not in " + message, message.contains(key));
}
}
}