Незнание класса водителя кажется странным ограничением.
Я бы выбрал специальный загрузчик классов, который после инициализации класса (я думаю, вы можете сделать это) вызывает DriverManager.getDrivers
и регистрирует любые новые драйверы, которые он находит. (У меня нет времени на написание кода.)
Хакерской альтернативой было бы загрузить весь ваш код (кроме начальной загрузки) в URLClassLoader
и addURL
к этому.
Редактировать: Итак, я написал некоторый код.
Он создает загрузчик классов для драйверов, который также содержит класс «scout», который пересылает DriverManager.drivers
(который является непослушным методом, чувствительным к вызывающим абонентам (новый!)). Поддельный драйвер в загрузчике класса приложения перенаправляет попытки подключения к любым динамически загружаемым драйверам во время запроса.
У меня нет драйверов для JDBC 4.0 или более поздней версии, на которых можно было бы это протестировать. Возможно, вы захотите изменить URL - вам понадобится класс Scout
и банка с драйверами.
import java.lang.reflect.*;
import java.net.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import java.util.stream.*;
class FakeJDBCDriver {
public static void main(String[] args) throws Exception {
URLClassLoader loader = URLClassLoader.newInstance(
new URL[] { new java.io.File("dynamic").toURI().toURL() },
FakeJDBCDriver.class.getClassLoader()
);
Class<?> scout = loader.loadClass("Scout");
Method driversMethod = scout.getMethod("drivers");
DriverManager.registerDriver(new Driver() {
public int getMajorVersion() {
return 0;
}
public int getMinorVersion() {
return 0;
}
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException();
}
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) {
return new DriverPropertyInfo[] { };
}
public boolean jdbcCompliant() {
return false;
}
public boolean acceptsURL(String url) throws SQLException {
if (url == null) {
throw new SQLException();
}
for (Iterator<Driver> iter=drivers(); iter.hasNext(); ) {
Driver driver = iter.next();
if (
driver.getClass().getClassLoader() == loader &&
driver.acceptsURL(url)
) {
return true;
}
}
return false;
}
public Connection connect(String url, Properties info) throws SQLException {
if (url == null) {
throw new SQLException();
}
for (Iterator<Driver> iter=drivers(); iter.hasNext(); ) {
Driver driver = iter.next();
if (
driver.getClass().getClassLoader() == loader &&
driver.acceptsURL(url)
) {
Connection connection = driver.connect(url, info);
if (connection != null) {
return connection;
}
}
}
return null;
}
private Iterator<Driver> drivers() {
try {
return ((Stream<Driver>)driversMethod.invoke(null)).iterator();
} catch (IllegalAccessException exc) {
throw new Error(exc);
} catch (InvocationTargetException exc) {
Throwable cause = exc.getTargetException();
if (cause instanceof Error) {
throw (Error)cause;
} else if (cause instanceof RuntimeException) {
throw (RuntimeException)cause;
} else {
throw new Error(exc);
}
}
}
});
// This the driver I'm trying to access, but isn't even in a jar.
Class.forName("MyDriver", true, loader);
// Just some nonsense to smoke test.
System.err.println(DriverManager.drivers().collect(Collectors.toList()));
System.err.println(DriverManager.getConnection("jdbc:mydriver"));
}
}
В каталоге dynamic
(относительно текущего рабочего каталога):
import java.sql.*;
public interface Scout {
public static java.util.stream.Stream<Driver> drivers() {
return DriverManager.drivers();
}
}
Я бы всегда предлагал избегать установки загрузчика класса контекста потока на что-либо кроме загрузчика, который все отрицает, или, возможно, null
.
Модули вполне могут позволить вам аккуратно загружать драйверы, но я не смотрел.