[#8145] Add an UnwrapProvider SPI that allows for unwrapping underlying JDBC types through proprietary APIs
This commit is contained in:
parent
d556bf8036
commit
ba5077d200
@ -305,6 +305,12 @@ public interface Configuration extends Serializable {
|
||||
*/
|
||||
DiagnosticsListenerProvider[] diagnosticsListenerProviders();
|
||||
|
||||
/**
|
||||
* Get the configured <code>UnwrapperProvider</code> from this
|
||||
* configuration.
|
||||
*/
|
||||
UnwrapperProvider unwrapperProvider();
|
||||
|
||||
/**
|
||||
* Get this configuration's underlying record mapper provider.
|
||||
*/
|
||||
@ -691,7 +697,7 @@ public interface Configuration extends Serializable {
|
||||
Configuration set(DiagnosticsListener... newDiagnosticsListeners);
|
||||
|
||||
/**
|
||||
* Change this configuration to hold a new diagnostics listener providers.
|
||||
* Change this configuration to hold new diagnostics listener providers.
|
||||
* <p>
|
||||
* This method is not thread-safe and should not be used in globally
|
||||
* available <code>Configuration</code> objects.
|
||||
@ -702,6 +708,30 @@ public interface Configuration extends Serializable {
|
||||
*/
|
||||
Configuration set(DiagnosticsListenerProvider... newDiagnosticsListenerProviders);
|
||||
|
||||
/**
|
||||
* Change this configuration to hold a new unwrapper.
|
||||
* <p>
|
||||
* This method is not thread-safe and should not be used in globally
|
||||
* available <code>Configuration</code> objects.
|
||||
*
|
||||
* @param newUnwrapper The new unwrapper to be contained in the changed
|
||||
* configuration.
|
||||
* @return The changed configuration.
|
||||
*/
|
||||
Configuration set(Unwrapper newUnwrapper);
|
||||
|
||||
/**
|
||||
* Change this configuration to hold a new unwrapper provider.
|
||||
* <p>
|
||||
* This method is not thread-safe and should not be used in globally
|
||||
* available <code>Configuration</code> objects.
|
||||
*
|
||||
* @param newUnwrapperProvider The new unwrapper provider to be contained in
|
||||
* the changed configuration.
|
||||
* @return The changed configuration.
|
||||
*/
|
||||
Configuration set(UnwrapperProvider newUnwrapperProvider);
|
||||
|
||||
/**
|
||||
* Change this configuration to hold a new converter provider.
|
||||
* <p>
|
||||
@ -987,6 +1017,25 @@ public interface Configuration extends Serializable {
|
||||
*/
|
||||
Configuration derive(DiagnosticsListenerProvider... newDiagnosticsListenerProviders);
|
||||
|
||||
/**
|
||||
* Create a derived configuration from this one, with a new unwrapper.
|
||||
*
|
||||
* @param newUnwrapper The new unwrapper to be contained in the derived
|
||||
* configuration.
|
||||
* @return The derived configuration.
|
||||
*/
|
||||
Configuration derive(Unwrapper newUnwrapper);
|
||||
|
||||
/**
|
||||
* Create a derived configuration from this one, with a new unwrapper
|
||||
* provider.
|
||||
*
|
||||
* @param newUnwrapperProvider The new unwrapper provider to be contained in
|
||||
* the derived configuration.
|
||||
* @return The derived configuration.
|
||||
*/
|
||||
Configuration derive(UnwrapperProvider newUnwrapperProvider);
|
||||
|
||||
/**
|
||||
* Create a derived configuration from this one, with new converter
|
||||
* provider.
|
||||
|
||||
78
jOOQ/src/main/java/org/jooq/Unwrapper.java
Normal file
78
jOOQ/src/main/java/org/jooq/Unwrapper.java
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Other licenses:
|
||||
* -----------------------------------------------------------------------------
|
||||
* Commercial licenses for this work are available. These replace the above
|
||||
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
* database integrations.
|
||||
*
|
||||
* For more information, please visit: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.Wrapper;
|
||||
|
||||
/**
|
||||
* An unwrapper SPI that can be used to override the default unwrapping
|
||||
* algorithm.
|
||||
* <p>
|
||||
* In some cases, jOOQ needs to get access to the native JDBC driver APIs in
|
||||
* order to call vendor specific methods, such as Oracle's
|
||||
* <code>OracleConnection.createARRAY()</code>. jOOQ doesn't expect clients to
|
||||
* provide a native JDBC {@link Connection} through the
|
||||
* {@link ConnectionProvider} SPI. Implementations may well provide jOOQ with
|
||||
* some proxy that implements things like logging, thread-bound
|
||||
* transactionality, connection pooling, etc.
|
||||
* <p>
|
||||
* In order to access the native API, {@link Wrapper#unwrap(Class)} needs to be
|
||||
* called, or in some cases, when third party libraries do not properly
|
||||
* implement this contract, some specific methods are called reflectively,
|
||||
* including:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li><code>org.springframework.jdbc.datasource.ConnectionProxy#getTargetConnection()</code></li>
|
||||
* <li><code>org.apache.commons.dbcp.DelegatingConnection#getDelegate()</code></li>
|
||||
* <li><code>org.jboss.jca.adapters.jdbc.WrappedConnection#getUnderlyingConnection()</code></li>
|
||||
* <li>...</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Not all such third party libraries are "known" to jOOQ, so clients can
|
||||
* implement their own unwrapper to support theirs.
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public interface Unwrapper {
|
||||
|
||||
/**
|
||||
* Unwrap a wrapped type from a JDBC {@link Wrapper}.
|
||||
*/
|
||||
<T> T unwrap(Wrapper wrapper, Class<T> iface);
|
||||
}
|
||||
58
jOOQ/src/main/java/org/jooq/UnwrapperProvider.java
Normal file
58
jOOQ/src/main/java/org/jooq/UnwrapperProvider.java
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Other licenses:
|
||||
* -----------------------------------------------------------------------------
|
||||
* Commercial licenses for this work are available. These replace the above
|
||||
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
* database integrations.
|
||||
*
|
||||
* For more information, please visit: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq;
|
||||
|
||||
import java.sql.Wrapper;
|
||||
|
||||
/**
|
||||
* A provider for the {@link Unwrapper} SPI which is used to override the
|
||||
* default behaviour when unwrapping JDBC types through
|
||||
* {@link Wrapper#unwrap(Class)}.
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
|
||||
public interface UnwrapperProvider {
|
||||
|
||||
/**
|
||||
* Provide an unwrapper for JDBC types.
|
||||
*/
|
||||
Unwrapper provide();
|
||||
}
|
||||
@ -75,6 +75,8 @@ import org.jooq.SQLDialect;
|
||||
import org.jooq.TransactionListener;
|
||||
import org.jooq.TransactionListenerProvider;
|
||||
import org.jooq.TransactionProvider;
|
||||
import org.jooq.Unwrapper;
|
||||
import org.jooq.UnwrapperProvider;
|
||||
import org.jooq.VisitListener;
|
||||
import org.jooq.VisitListenerProvider;
|
||||
import org.jooq.conf.Settings;
|
||||
@ -91,7 +93,6 @@ import org.jooq.impl.Tools.DataCacheKey;
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DefaultConfiguration implements Configuration {
|
||||
|
||||
/**
|
||||
@ -118,6 +119,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
private transient VisitListenerProvider[] visitListenerProviders;
|
||||
private transient TransactionListenerProvider[] transactionListenerProviders;
|
||||
private transient DiagnosticsListenerProvider[] diagnosticsListenerProviders;
|
||||
private transient UnwrapperProvider unwrapperProvider;
|
||||
private transient ConverterProvider converterProvider;
|
||||
|
||||
// [#7062] Apart from the possibility of containing user defined objects, the data
|
||||
@ -163,6 +165,11 @@ public class DefaultConfiguration implements Configuration {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
dialect,
|
||||
SettingsTools.defaultSettings(),
|
||||
null
|
||||
@ -539,7 +546,14 @@ public class DefaultConfiguration implements Configuration {
|
||||
* configuration properties in the future, without breaking client code.
|
||||
* Consider creating a configuration by chaining calls to various
|
||||
* <code>derive()</code> methods.
|
||||
*
|
||||
* @deprecated Use
|
||||
* {@link #DefaultConfiguration(ConnectionProvider, ExecutorProvider, TransactionProvider, RecordMapperProvider, RecordUnmapperProvider, RecordListenerProvider[], ExecuteListenerProvider[], VisitListenerProvider[], TransactionListenerProvider[], DiagnosticsListenerProvider[], UnwrapperProvider, ConverterProvider, SQLDialect, Settings, Map)}
|
||||
* instead. This constructor is maintained to provide jOOQ 3.2,
|
||||
* 3.3, 3.7, 3.8, 3.9, 3.10, 3.11 backwards-compatibility if
|
||||
* called with reflection from Spring configurations.
|
||||
*/
|
||||
@Deprecated
|
||||
DefaultConfiguration(
|
||||
ConnectionProvider connectionProvider,
|
||||
MetaProvider metaProvider,
|
||||
@ -556,6 +570,59 @@ public class DefaultConfiguration implements Configuration {
|
||||
|
||||
Clock clock,
|
||||
|
||||
SQLDialect dialect,
|
||||
Settings settings,
|
||||
Map<Object, Object> data)
|
||||
{
|
||||
this(
|
||||
connectionProvider,
|
||||
metaProvider,
|
||||
executorProvider,
|
||||
transactionProvider,
|
||||
recordMapperProvider,
|
||||
recordUnmapperProvider,
|
||||
recordListenerProviders,
|
||||
executeListenerProviders,
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
null,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
|
||||
dialect,
|
||||
settings,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the actual configuration object.
|
||||
* <p>
|
||||
* This constructor has been made package-private to allow for adding new
|
||||
* configuration properties in the future, without breaking client code.
|
||||
* Consider creating a configuration by chaining calls to various
|
||||
* <code>derive()</code> methods.
|
||||
*/
|
||||
DefaultConfiguration(
|
||||
ConnectionProvider connectionProvider,
|
||||
MetaProvider metaProvider,
|
||||
ExecutorProvider executorProvider,
|
||||
TransactionProvider transactionProvider,
|
||||
RecordMapperProvider recordMapperProvider,
|
||||
RecordUnmapperProvider recordUnmapperProvider,
|
||||
RecordListenerProvider[] recordListenerProviders,
|
||||
ExecuteListenerProvider[] executeListenerProviders,
|
||||
VisitListenerProvider[] visitListenerProviders,
|
||||
TransactionListenerProvider[] transactionListenerProviders,
|
||||
DiagnosticsListenerProvider[] diagnosticsListenerProviders,
|
||||
UnwrapperProvider unwrapperProvider,
|
||||
ConverterProvider converterProvider,
|
||||
|
||||
Clock clock,
|
||||
|
||||
SQLDialect dialect,
|
||||
Settings settings,
|
||||
Map<Object, Object> data)
|
||||
@ -571,6 +638,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
set(visitListenerProviders);
|
||||
set(transactionListenerProviders);
|
||||
set(diagnosticsListenerProviders);
|
||||
set(unwrapperProvider);
|
||||
set(converterProvider);
|
||||
|
||||
set(clock);
|
||||
@ -625,6 +693,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -649,6 +718,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -678,6 +748,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -702,6 +773,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -731,6 +803,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -760,6 +833,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -789,6 +863,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -818,6 +893,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -847,6 +923,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
newVisitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -876,6 +953,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
newTransactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -905,6 +983,37 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
newDiagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
|
||||
dialect,
|
||||
settings,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Configuration derive(Unwrapper newUnwrapper) {
|
||||
return derive(new UnwrapperWrapper(newUnwrapper));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Configuration derive(UnwrapperProvider newUnwrapperProvider) {
|
||||
return new DefaultConfiguration(
|
||||
connectionProvider,
|
||||
metaProvider,
|
||||
executorProvider,
|
||||
transactionProvider,
|
||||
recordMapperProvider,
|
||||
recordUnmapperProvider,
|
||||
recordListenerProviders,
|
||||
executeListenerProviders,
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
newUnwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -929,6 +1038,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
newConverterProvider,
|
||||
|
||||
clock,
|
||||
@ -954,6 +1064,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
newClock,
|
||||
dialect,
|
||||
@ -977,6 +1088,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -1001,6 +1113,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders,
|
||||
transactionListenerProviders,
|
||||
diagnosticsListenerProviders,
|
||||
unwrapperProvider,
|
||||
converterProvider,
|
||||
|
||||
clock,
|
||||
@ -1076,7 +1189,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration set(RecordMapper<?, ?> newRecordMapper) {
|
||||
public final Configuration set(RecordMapper<?, ?> newRecordMapper) {
|
||||
return set(new RecordMapperWrapper(newRecordMapper));
|
||||
}
|
||||
|
||||
@ -1087,7 +1200,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration set(RecordUnmapper<?, ?> newRecordUnmapper) {
|
||||
public final Configuration set(RecordUnmapper<?, ?> newRecordUnmapper) {
|
||||
return set(new RecordUnmapperWrapper(newRecordUnmapper));
|
||||
}
|
||||
|
||||
@ -1167,6 +1280,19 @@ public class DefaultConfiguration implements Configuration {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Configuration set(Unwrapper newUnwrapper) {
|
||||
return newUnwrapper != null
|
||||
? set(new UnwrapperWrapper(newUnwrapper))
|
||||
: set((UnwrapperProvider) null) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Configuration set(UnwrapperProvider newUnwrapperProvider) {
|
||||
this.unwrapperProvider = newUnwrapperProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Configuration set(ConverterProvider newConverterProvider) {
|
||||
this.converterProvider = newConverterProvider != null
|
||||
@ -1387,6 +1513,13 @@ public class DefaultConfiguration implements Configuration {
|
||||
return diagnosticsListenerProviders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final UnwrapperProvider unwrapperProvider() {
|
||||
return unwrapperProvider != null
|
||||
? unwrapperProvider
|
||||
: new DefaultUnwrapperProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ConverterProvider converterProvider() {
|
||||
return converterProvider;
|
||||
@ -1476,6 +1609,10 @@ public class DefaultConfiguration implements Configuration {
|
||||
oos.writeObject(cloneSerializables(transactionListenerProviders));
|
||||
oos.writeObject(cloneSerializables(diagnosticsListenerProviders));
|
||||
|
||||
oos.writeObject(unwrapperProvider instanceof Serializable
|
||||
? unwrapperProvider
|
||||
: null);
|
||||
|
||||
oos.writeObject(converterProvider instanceof Serializable
|
||||
? converterProvider
|
||||
: null);
|
||||
@ -1520,6 +1657,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
visitListenerProviders = (VisitListenerProvider[]) ois.readObject();
|
||||
transactionListenerProviders = (TransactionListenerProvider[]) ois.readObject();
|
||||
diagnosticsListenerProviders = (DiagnosticsListenerProvider[]) ois.readObject();
|
||||
unwrapperProvider = (UnwrapperProvider) ois.readObject();
|
||||
converterProvider = (ConverterProvider) ois.readObject();
|
||||
data = new ConcurrentHashMap<Object, Object>();
|
||||
|
||||
@ -1572,4 +1710,17 @@ public class DefaultConfiguration implements Configuration {
|
||||
return (RecordUnmapper<E, R>) newRecordUnmapper;
|
||||
}
|
||||
}
|
||||
|
||||
private final class UnwrapperWrapper implements UnwrapperProvider {
|
||||
private final Unwrapper newUnwrapper;
|
||||
|
||||
private UnwrapperWrapper(Unwrapper newUnwrapper) {
|
||||
this.newUnwrapper = newUnwrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unwrapper provide() {
|
||||
return newUnwrapper;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,8 +77,6 @@ import org.jooq.Update;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
import org.jooq.tools.jdbc.JDBCUtils;
|
||||
import org.jooq.tools.reflect.Reflect;
|
||||
import org.jooq.tools.reflect.ReflectException;
|
||||
|
||||
/**
|
||||
* A default implementation for the {@link ExecuteContext}.
|
||||
@ -301,36 +299,16 @@ class DefaultExecuteContext implements ExecuteContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* [#3696] We shouldn't infinitely attempt to unwrap connections.
|
||||
*/
|
||||
private static int maxUnwrappedConnections = 256;
|
||||
|
||||
/**
|
||||
* [#7589] No infinite attempts to unwrap statements, either.
|
||||
*/
|
||||
private static int maxUnwrappedStatements = 256;
|
||||
|
||||
/**
|
||||
* Get the registered connection's "target connection" if applicable.
|
||||
* <p>
|
||||
* This will try to unwrap any native connection if it has been wrapped with
|
||||
* any of:
|
||||
* <ul>
|
||||
* <li><code>org.springframework.jdbc.datasource.ConnectionProxy</code></li>
|
||||
* <li><code>org.apache.commons.dbcp.DelegatingConnection</code></li>
|
||||
* <li><code>org.jboss.jca.adapters.jdbc.WrappedConnection</code></li>
|
||||
* <li>...</li>
|
||||
* </ul>
|
||||
* Get the registered connection's "target connection" through
|
||||
* {@link Configuration#unwrapperProvider()} if applicable.
|
||||
* <p>
|
||||
* It can be safely assumed that such a connection is available once the
|
||||
* {@link ExecuteContext} has been established, until the statement is
|
||||
* closed.
|
||||
*/
|
||||
static final Connection localTargetConnection() {
|
||||
static final Connection localTargetConnection(Configuration configuration) {
|
||||
Connection result = localConnection();
|
||||
|
||||
unwrappingLoop:
|
||||
for (int i = 0; i < maxUnwrappedConnections; i++) {
|
||||
|
||||
|
||||
|
||||
@ -352,48 +330,7 @@ class DefaultExecuteContext implements ExecuteContext {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Unwrap nested Spring org.springframework.jdbc.datasource.ConnectionProxy objects
|
||||
try {
|
||||
Connection r = Reflect.on(result).call("getTargetConnection").get();
|
||||
if (result != r && r != null) {
|
||||
result = r;
|
||||
continue unwrappingLoop;
|
||||
}
|
||||
}
|
||||
catch (ReflectException ignore) {}
|
||||
|
||||
// Unwrap nested DBCP org.apache.commons.dbcp.DelegatingConnection
|
||||
try {
|
||||
Connection r = Reflect.on(result).call("getDelegate").get();
|
||||
if (result != r && r != null) {
|
||||
result = r;
|
||||
continue unwrappingLoop;
|
||||
}
|
||||
}
|
||||
catch (ReflectException ignore) {}
|
||||
|
||||
// [#7641] Unwrap nested org.jboss.jca.adapters.jdbc.WrappedConnection
|
||||
try {
|
||||
Connection r = Reflect.on(result).call("getUnderlyingConnection").get();
|
||||
if (result != r && r != null) {
|
||||
result = r;
|
||||
continue unwrappingLoop;
|
||||
}
|
||||
}
|
||||
catch (ReflectException ignore) {}
|
||||
|
||||
// No unwrapping method was found.
|
||||
break;
|
||||
}
|
||||
|
||||
log.info("Could not unwrap native Connection type. Consider implementing an org.jooq.UnwrapperProvider");
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
@ -406,11 +343,9 @@ class DefaultExecuteContext implements ExecuteContext {
|
||||
* <li>...</li>
|
||||
* </ul>
|
||||
*/
|
||||
static final PreparedStatement targetPreparedStatement(PreparedStatement stmt) {
|
||||
static final PreparedStatement targetPreparedStatement(Configuration configuration, PreparedStatement stmt) {
|
||||
PreparedStatement result = stmt;
|
||||
|
||||
unwrappingLoop:
|
||||
for (int i = 0; i < maxUnwrappedStatements; i++) {
|
||||
|
||||
|
||||
|
||||
@ -432,38 +367,7 @@ class DefaultExecuteContext implements ExecuteContext {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Unwrap nested DBCP org.apache.commons.dbcp.DelegatingPreparedStatement
|
||||
try {
|
||||
PreparedStatement r = Reflect.on(result).call("getDelegate").get();
|
||||
if (result != r && r != null) {
|
||||
result = r;
|
||||
continue unwrappingLoop;
|
||||
}
|
||||
}
|
||||
catch (ReflectException ignore) {}
|
||||
|
||||
// [#7641] Unwrap nested org.jboss.jca.adapters.jdbc.WrappedStatement
|
||||
try {
|
||||
PreparedStatement r = Reflect.on(result).call("getUnderlyingStatement").get();
|
||||
if (result != r && r != null) {
|
||||
result = r;
|
||||
continue unwrappingLoop;
|
||||
}
|
||||
}
|
||||
catch (ReflectException ignore) {}
|
||||
|
||||
// No unwrapping method was found.
|
||||
break;
|
||||
}
|
||||
|
||||
log.info("Could not unwrap native PreparedStatement type. Consider implementing an org.jooq.UnwrapperProvider");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
201
jOOQ/src/main/java/org/jooq/impl/DefaultUnwrapperProvider.java
Normal file
201
jOOQ/src/main/java/org/jooq/impl/DefaultUnwrapperProvider.java
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Other licenses:
|
||||
* -----------------------------------------------------------------------------
|
||||
* Commercial licenses for this work are available. These replace the above
|
||||
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
* database integrations.
|
||||
*
|
||||
* For more information, please visit: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Wrapper;
|
||||
|
||||
import org.jooq.Unwrapper;
|
||||
import org.jooq.UnwrapperProvider;
|
||||
import org.jooq.tools.reflect.Reflect;
|
||||
import org.jooq.tools.reflect.ReflectException;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
final class DefaultUnwrapperProvider implements UnwrapperProvider {
|
||||
|
||||
static final Unwrapper INSTANCE = new DefaultUnwrapper();
|
||||
|
||||
static final class DefaultUnwrapper implements Unwrapper {
|
||||
|
||||
/**
|
||||
* [#3696] We shouldn't infinitely attempt to unwrap connections.
|
||||
*/
|
||||
private static int maxUnwrappedConnections = 256;
|
||||
|
||||
/**
|
||||
* [#7589] No infinite attempts to unwrap statements, either.
|
||||
*/
|
||||
private static int maxUnwrappedStatements = 256;
|
||||
|
||||
@Override
|
||||
public <T> T unwrap(Wrapper wrapper, Class<T> iface) {
|
||||
if (wrapper instanceof Connection)
|
||||
return unwrap((Connection) wrapper, iface);
|
||||
else if (wrapper instanceof Statement)
|
||||
return unwrap((Statement) wrapper, iface);
|
||||
else
|
||||
throw new IllegalArgumentException("Cannot unwrap: " + wrapper);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T unwrap(Connection wrapper, Class<T> iface) {
|
||||
Connection result = wrapper;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return (T) result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T unwrap(Statement wrapper, Class<T> iface) {
|
||||
Statement result = wrapper;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Unwrap nested DBCP org.apache.commons.dbcp.DelegatingPreparedStatement
|
||||
try {
|
||||
PreparedStatement r = Reflect.on(result).call("getDelegate").get();
|
||||
if (result != r && r != null) {
|
||||
result = r;
|
||||
continue unwrappingLoop;
|
||||
}
|
||||
}
|
||||
catch (ReflectException ignore) {}
|
||||
|
||||
// [#7641] Unwrap nested org.jboss.jca.adapters.jdbc.WrappedStatement
|
||||
try {
|
||||
PreparedStatement r = Reflect.on(result).call("getUnderlyingStatement").get();
|
||||
if (result != r && r != null) {
|
||||
result = r;
|
||||
continue unwrappingLoop;
|
||||
}
|
||||
}
|
||||
catch (ReflectException ignore) {}
|
||||
|
||||
// No unwrapping method was found.
|
||||
break;
|
||||
}
|
||||
/* [/pro] */
|
||||
|
||||
return (T) result;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Unwrapper provide() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
@ -64,6 +64,8 @@ import org.jooq.SQLDialect;
|
||||
import org.jooq.TransactionListener;
|
||||
import org.jooq.TransactionListenerProvider;
|
||||
import org.jooq.TransactionProvider;
|
||||
import org.jooq.Unwrapper;
|
||||
import org.jooq.UnwrapperProvider;
|
||||
import org.jooq.VisitListener;
|
||||
import org.jooq.VisitListenerProvider;
|
||||
import org.jooq.conf.Settings;
|
||||
@ -175,6 +177,11 @@ public class MockConfiguration implements Configuration {
|
||||
return delegate.diagnosticsListenerProviders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnwrapperProvider unwrapperProvider() {
|
||||
return delegate.unwrapperProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConverterProvider converterProvider() {
|
||||
return delegate.converterProvider();
|
||||
@ -312,6 +319,16 @@ public class MockConfiguration implements Configuration {
|
||||
return delegate.set(newDiagnosticsListenerProviders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration set(Unwrapper newUnwrapper) {
|
||||
return delegate.set(newUnwrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration set(UnwrapperProvider newUnwrapperProvider) {
|
||||
return delegate.set(newUnwrapperProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration set(ConverterProvider newConverterProvider) {
|
||||
return delegate.set(newConverterProvider);
|
||||
@ -444,6 +461,16 @@ public class MockConfiguration implements Configuration {
|
||||
return delegate.derive(newDiagnosticsListenerProviders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration derive(Unwrapper newUnwrapper) {
|
||||
return delegate.derive(newUnwrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration derive(UnwrapperProvider newUnwrapperProvider) {
|
||||
return delegate.derive(newUnwrapperProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration derive(ConverterProvider newConverterProvider) {
|
||||
return delegate.derive(newConverterProvider);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user