Repository: tomee Updated Branches: refs/heads/master f54d40789 -> 2b736c4c4
TOMEE-1714 custom handler to wrap a datasource Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/2b736c4c Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/2b736c4c Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/2b736c4c Branch: refs/heads/master Commit: 2b736c4c4519486a983ca09c79253ac99f53b1e5 Parents: f54d407 Author: Romain manni-Bucau <rmannibu...@gmail.com> Authored: Wed Feb 17 14:42:41 2016 +0100 Committer: Romain manni-Bucau <rmannibu...@gmail.com> Committed: Wed Feb 17 14:42:41 2016 +0100 ---------------------------------------------------------------------- .../resource/jdbc/DataSourceFactory.java | 41 +++++++++++++ .../DataSourceFactoryCustomHandlerTest.java | 63 ++++++++++++++++++++ 2 files changed, 104 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/2b736c4c/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java index 49b1fb1..4a0c265 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java @@ -45,6 +45,7 @@ import java.io.Flushable; import java.io.IOException; import java.io.Serializable; import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy; import java.sql.Driver; import java.sql.SQLException; @@ -75,6 +76,8 @@ public class DataSourceFactory { public static final String GLOBAL_FLUSH_PROPERTY = "openejb.jdbc.flushable"; public static final String POOL_PROPERTY = "openejb.datasource.pool"; public static final String DATA_SOURCE_CREATOR_PROP = "DataSourceCreator"; + public static final String HANDLER_PROPERTY = "TomEEProxyHandler"; + public static final String GLOBAL_HANDLER_PROPERTY = "openejb.jdbc.handler"; private static final Map<CommonDataSource, AlternativeDriver> driverByDataSource = new HashMap<>(); @@ -97,6 +100,7 @@ public class DataSourceFactory { final Properties properties = asProperties(definition); final Set<String> originalKeys = properties.stringPropertyNames(); + final String handler = SystemInstance.get().getOptions().get(GLOBAL_HANDLER_PROPERTY, (String) properties.remove(HANDLER_PROPERTY)); boolean flushable = SystemInstance.get().getOptions().get(GLOBAL_FLUSH_PROPERTY, "true".equalsIgnoreCase((String) properties.remove(FLUSHABLE_PROPERTY))); @@ -239,6 +243,8 @@ public class DataSourceFactory { } } + ds = wrapIfNeeded(handler, ds); + if (logSql) { ds = makeItLogging(ds, logPackages); } @@ -273,6 +279,8 @@ public class DataSourceFactory { resettableDataSourceHandler.updateDelegate(ds); ds = makeSerializableFlushableDataSourceProxy(ds, resettableDataSourceHandler); } + } else { + ds = wrapIfNeeded(handler, ds); } return ds; @@ -283,6 +291,32 @@ public class DataSourceFactory { } } + private static CommonDataSource wrapIfNeeded(final String handler, final CommonDataSource ds) throws InstantiationException, IllegalAccessException { + if (handler != null) { + try { + final Class<?> handlerClass = Thread.currentThread().getContextClassLoader().loadClass(handler); + InvocationHandler instance; + try { + instance = InvocationHandler.class.cast(handlerClass.getConstructor(DataSource.class).newInstance(ds)); + } catch (final InvocationTargetException e) { + throw new IllegalStateException(e.getCause()); + } catch (final NoSuchMethodException e) { + try { + instance = InvocationHandler.class.cast(handlerClass.getConstructor(CommonDataSource.class).newInstance(ds)); + } catch (final InvocationTargetException e2) { + throw new IllegalStateException(e.getCause()); + } catch (final NoSuchMethodException e2) { + instance = InvocationHandler.class.cast(handlerClass.newInstance()); + } + } + return wrapWithHandler(ds, instance); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Can't find handler: " + handler, e); + } + } + return ds; + } + public static CommonDataSource makeSerializableFlushableDataSourceProxy(final CommonDataSource ds, final InvocationHandler handler) { return (CommonDataSource) Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), @@ -322,6 +356,13 @@ public class DataSourceFactory { creatorByDataSource.put(ds, creator); } + private static CommonDataSource wrapWithHandler(final CommonDataSource ds, final InvocationHandler instance) { + return (CommonDataSource) Proxy.newProxyInstance( + Thread.currentThread().getContextClassLoader(), + new Class<?>[]{DataSource.class.isInstance(ds) ? DataSource.class : XADataSource.class, Serializable.class}, + instance); + } + public static DataSource makeItLogging(final CommonDataSource ds, final String packagesStr) { final String[] pck = packagesStr == null ? null : packagesStr.split(" *, *"); return (DataSource) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), http://git-wip-us.apache.org/repos/asf/tomee/blob/2b736c4c/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/DataSourceFactoryCustomHandlerTest.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/DataSourceFactoryCustomHandlerTest.java b/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/DataSourceFactoryCustomHandlerTest.java new file mode 100644 index 0000000..03a020f --- /dev/null +++ b/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/DataSourceFactoryCustomHandlerTest.java @@ -0,0 +1,63 @@ +/* + * 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.openejb.resource.jdbc; + +import org.apache.openejb.junit.ApplicationComposer; +import org.apache.openejb.testing.Classes; +import org.apache.openejb.testing.ContainerProperties; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.annotation.Resource; +import javax.sql.DataSource; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import static org.junit.Assert.assertTrue; + +@RunWith(ApplicationComposer.class) +@Classes +@ContainerProperties({ + @ContainerProperties.Property( + name = "DataSourceFactoryCustomHandlerTest", + value = "new://Resource?type=DataSource"), + @ContainerProperties.Property( + name = "DataSourceFactoryCustomHandlerTest.TomEEProxyHandler", + value = "org.apache.openejb.resource.jdbc.DataSourceFactoryCustomHandlerTest$TheHandler") +}) +public class DataSourceFactoryCustomHandlerTest { + @Resource + private DataSource ds; + + @Test + public void run() { + assertTrue(Proxy.isProxyClass(ds.getClass()) && TheHandler.class.isInstance(Proxy.getInvocationHandler(ds))); + } + public static class TheHandler implements InvocationHandler { + private final DataSource ds; + + public TheHandler(final DataSource ds) { + this.ds = ds; + } + + @Override + public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { + return method.invoke(ds, args); + } + } +}