mirror of https://github.com/apache/nifi.git
JDBC driver can be loaded from external location using URLClassLoader
Signed-off-by: Toivo Adams <toivo.adams@gmail.com> Signed-off-by: Mark Payne <markap14@hotmail.com>
This commit is contained in:
parent
864e0996ca
commit
1682d62d7f
|
@ -20,6 +20,8 @@ import java.net.MalformedURLException;
|
|||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -184,7 +186,7 @@ public class DBCPConnectionPool extends AbstractControllerService implements DBC
|
|||
|
||||
// Optional driver URL, when exist, this URL will be used to locate driver jar file location
|
||||
String urlString = context.getProperty(DB_DRIVER_JAR_URL).getValue();
|
||||
dataSource.setDriverClassLoader( getDriverClassLoader(urlString) );
|
||||
dataSource.setDriverClassLoader( getDriverClassLoader(urlString, drv) );
|
||||
|
||||
String dburl = dbsystem.buildUrl(host, port, dbname);
|
||||
|
||||
|
@ -210,14 +212,27 @@ public class DBCPConnectionPool extends AbstractControllerService implements DBC
|
|||
* using Thread.currentThread().getContextClassLoader();
|
||||
* will ensure that you are using the ClassLoader for you NAR.
|
||||
* @throws InitializationException
|
||||
*/
|
||||
protected ClassLoader getDriverClassLoader(String urlString) throws InitializationException {
|
||||
*/
|
||||
protected ClassLoader getDriverClassLoader(String urlString, String drvName) throws InitializationException {
|
||||
if (urlString!=null && urlString.length()>0) {
|
||||
try {
|
||||
URL[] urls = new URL[] { new URL(urlString) };
|
||||
return new URLClassLoader(urls);
|
||||
URLClassLoader ucl = new URLClassLoader(urls);
|
||||
|
||||
// Workaround which allows to use URLClassLoader for JDBC driver loading.
|
||||
// (Because the DriverManager will refuse to use a driver not loaded by the system ClassLoader.)
|
||||
Class<?> clazz = Class.forName(drvName, true, ucl);
|
||||
if (clazz==null)
|
||||
throw new InitializationException("Can't load Database Driver " + drvName);
|
||||
Driver driver = (Driver) clazz.newInstance();
|
||||
DriverManager.registerDriver( new DriverShim(driver) );
|
||||
|
||||
return ucl;
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
throw new InitializationException("Invalid Database Driver Jar Url", e);
|
||||
} catch (Exception e) {
|
||||
throw new InitializationException("Can't load Database Driver", e);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.nifi.dbcp;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverPropertyInfo;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLFeatureNotSupportedException;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Workaround which allows to use URLClassLoader for JDBC driver loading.
|
||||
* (Because the DriverManager will refuse to use a driver not loaded by the system ClassLoader.)
|
||||
*
|
||||
*/
|
||||
class DriverShim implements Driver {
|
||||
private Driver driver;
|
||||
|
||||
DriverShim(Driver d) {
|
||||
this.driver = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsURL(String u) throws SQLException {
|
||||
return this.driver.acceptsURL(u);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection connect(String u, Properties p) throws SQLException {
|
||||
return this.driver.connect(u, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMajorVersion() {
|
||||
return this.driver.getMajorVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinorVersion() {
|
||||
return this.driver.getMinorVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {
|
||||
return this.driver.getPropertyInfo(u, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean jdbcCompliant() {
|
||||
return this.driver.jdbcCompliant();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||
return driver.getParentLogger();
|
||||
}
|
||||
|
||||
}
|
|
@ -51,7 +51,7 @@ public class DBCPServiceTest {
|
|||
* Unknown database system.
|
||||
*
|
||||
*/
|
||||
// @Test
|
||||
@Test
|
||||
public void testUnknownDatabaseSystem() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final DBCPConnectionPool service = new DBCPConnectionPool();
|
||||
|
@ -64,7 +64,7 @@ public class DBCPServiceTest {
|
|||
/**
|
||||
* Missing property values.
|
||||
*/
|
||||
// @Test
|
||||
@Test
|
||||
public void testMissingPropertyValues() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final DBCPConnectionPool service = new DBCPConnectionPool();
|
||||
|
@ -78,7 +78,7 @@ public class DBCPServiceTest {
|
|||
* Connect, create table, insert, select, drop table.
|
||||
*
|
||||
*/
|
||||
// @Test
|
||||
@Test
|
||||
public void testCreateInsertSelect() throws InitializationException, SQLException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final DBCPConnectionPool service = new DBCPConnectionPool();
|
||||
|
@ -120,7 +120,7 @@ public class DBCPServiceTest {
|
|||
* Connect, create table, insert, select, drop table.
|
||||
*
|
||||
*/
|
||||
// @Test
|
||||
@Test
|
||||
public void testExternalJDBCDriverUsage() throws InitializationException, SQLException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final DBCPConnectionPool service = new DBCPConnectionPool();
|
||||
|
@ -136,7 +136,7 @@ public class DBCPServiceTest {
|
|||
runner.setProperty(service, DBCPConnectionPool.DB_DRIVER_JAR_URL, "file:///var/tmp/mariadb-java-client-1.1.7.jar");
|
||||
|
||||
|
||||
runner.setProperty(service, DBCPConnectionPool.DB_HOST, "127.0.0.1"); // localhost
|
||||
runner.setProperty(service, DBCPConnectionPool.DB_HOST, "localhost"); // localhost
|
||||
runner.setProperty(service, DBCPConnectionPool.DB_NAME, "testdb");
|
||||
runner.setProperty(service, DBCPConnectionPool.DB_USER, "tester");
|
||||
runner.setProperty(service, DBCPConnectionPool.DB_PASSWORD, "testerp");
|
||||
|
@ -163,7 +163,7 @@ public class DBCPServiceTest {
|
|||
* Get many times, after a while pool should not contain any available connection
|
||||
* and getConnection should fail.
|
||||
*/
|
||||
// @Test
|
||||
@Test
|
||||
public void testExhaustPool() throws InitializationException, SQLException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final DBCPConnectionPool service = new DBCPConnectionPool();
|
||||
|
@ -197,7 +197,7 @@ public class DBCPServiceTest {
|
|||
* Get many times, release immediately
|
||||
* and getConnection should not fail.
|
||||
*/
|
||||
// @Test
|
||||
@Test
|
||||
public void testGetManyNormal() throws InitializationException, SQLException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final DBCPConnectionPool service = new DBCPConnectionPool();
|
||||
|
@ -226,7 +226,7 @@ public class DBCPServiceTest {
|
|||
}
|
||||
|
||||
|
||||
// @Test
|
||||
@Test
|
||||
public void testDriverLoad() throws ClassNotFoundException {
|
||||
Class<?> clazz = Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
|
||||
assertNotNull(clazz);
|
||||
|
@ -244,29 +244,36 @@ public class DBCPServiceTest {
|
|||
|
||||
ClassLoader parent = Thread.currentThread().getContextClassLoader();
|
||||
URLClassLoader ucl = new URLClassLoader(urls,parent);
|
||||
// URLClassLoader ucl = new URLClassLoader(urls);
|
||||
|
||||
Class<?> clazz = Class.forName("org.mariadb.jdbc.Driver", true, ucl);
|
||||
assertNotNull(clazz);
|
||||
|
||||
Driver driver = (Driver) clazz.newInstance();
|
||||
Driver shim = new DriverShim(driver);
|
||||
DriverManager.registerDriver( shim );
|
||||
|
||||
// Driver is found when using URL ClassLoader
|
||||
assertTrue( isDriverAllowed(driver, ucl) );
|
||||
|
||||
// Driver is not found when using parent ClassLoader
|
||||
// unfortunately DriverManager will use caller ClassLoadar and driver is not found !!!
|
||||
assertTrue( isDriverAllowed(driver, parent) );
|
||||
// assertTrue( isDriverAllowed(driver, parent) );
|
||||
|
||||
// DriverManager.registerDriver( (Driver) clazz.newInstance());
|
||||
Enumeration<Driver> drivers = DriverManager.getDrivers();
|
||||
while (drivers.hasMoreElements()) {
|
||||
driver = (Driver) drivers.nextElement();
|
||||
System.out.println(driver);
|
||||
}
|
||||
|
||||
Driver driver2 = DriverManager.getDriver("jdbc:mariadb://localhost:3306/testdb");
|
||||
assertNotNull(driver2);
|
||||
|
||||
Connection connection = DriverManager.getConnection("jdbc:mariadb://localhost:3306/testdb","tester","testerp");
|
||||
assertNotNull(connection);
|
||||
connection.close();
|
||||
|
||||
// Driver driver = DriverManager.getDriver("jdbc:mariadb://127.0.0.1:3306/testdb");
|
||||
// assertNotNull(driver);
|
||||
DriverManager.deregisterDriver(shim);
|
||||
}
|
||||
|
||||
|
||||
|
@ -299,7 +306,7 @@ public class DBCPServiceTest {
|
|||
}
|
||||
|
||||
//==================================== problem solving - no suitable driver found, mariadb =========================================
|
||||
|
||||
// method isDriverAllowed is from DriverManager
|
||||
private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
|
||||
boolean result = false;
|
||||
if(driver != null) {
|
||||
|
@ -318,6 +325,4 @@ public class DBCPServiceTest {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue