From ebca8adaa2988be76e97967182d28d0a3e0c634a Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 12 Apr 2013 12:00:30 +0200 Subject: [PATCH] [#2388] Replace Configuration's List with ExecuteListenerProvider[] to simplify correct and thread-safe client implementations --- jOOQ-test/src/org/jooq/test/ASETest.java | 2 +- jOOQ-test/src/org/jooq/test/BaseTest.java | 22 ++++---- jOOQ-test/src/org/jooq/test/CUBRIDTest.java | 2 +- jOOQ-test/src/org/jooq/test/DB2Test.java | 2 +- jOOQ-test/src/org/jooq/test/DerbyTest.java | 2 +- jOOQ-test/src/org/jooq/test/FirebirdTest.java | 2 +- jOOQ-test/src/org/jooq/test/H2Test.java | 2 +- jOOQ-test/src/org/jooq/test/HSQLDBTest.java | 2 +- jOOQ-test/src/org/jooq/test/HSQLDBTest2.java | 2 +- jOOQ-test/src/org/jooq/test/IngresTest.java | 2 +- jOOQ-test/src/org/jooq/test/MySQLTest.java | 2 +- .../org/jooq/test/MySQLTestSchemaMapping.java | 2 +- .../org/jooq/test/MySQLTestSchemaRewrite.java | 2 +- jOOQ-test/src/org/jooq/test/OracleTest.java | 2 +- .../src/org/jooq/test/OracleTestInline.java | 2 +- jOOQ-test/src/org/jooq/test/PostgresTest.java | 2 +- .../src/org/jooq/test/SQLServerTest.java | 2 +- .../org/jooq/test/SQLServerTestInline.java | 2 +- jOOQ-test/src/org/jooq/test/SQLiteTest.java | 2 +- jOOQ-test/src/org/jooq/test/SybaseTest.java | 2 +- .../jooq/test/_/testcases/BenchmarkTests.java | 4 +- .../_/testcases/ExecuteListenerTests.java | 19 +++---- .../jooq/test/_/testcases/GeneralTests.java | 3 +- .../jooq/test/_/testcases/StatementTests.java | 3 +- .../src/org/jooq/test/jOOQAbstractTest.java | 50 +++++++++++++------ .../src/main/java/org/jooq/Configuration.java | 4 +- .../org/jooq/ExecuteListenerProvider.java | 22 ++++---- .../main/java/org/jooq/impl/BatchCRUD.java | 15 +++--- .../org/jooq/impl/DefaultConfiguration.java | 42 +++++++++------- .../impl/DefaultExecuteListenerProvider.java | 49 ++++++++---------- .../java/org/jooq/impl/ExecuteListeners.java | 32 +++++++++++- jOOQ/src/main/java/org/jooq/impl/Utils.java | 29 ++++------- 32 files changed, 180 insertions(+), 152 deletions(-) diff --git a/jOOQ-test/src/org/jooq/test/ASETest.java b/jOOQ-test/src/org/jooq/test/ASETest.java index c644f07361..f1ed49b0f1 100644 --- a/jOOQ-test/src/org/jooq/test/ASETest.java +++ b/jOOQ-test/src/org/jooq/test/ASETest.java @@ -125,7 +125,7 @@ public class ASETest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.ASE, settings); } diff --git a/jOOQ-test/src/org/jooq/test/BaseTest.java b/jOOQ-test/src/org/jooq/test/BaseTest.java index c939bb74f8..04890bcc3a 100644 --- a/jOOQ-test/src/org/jooq/test/BaseTest.java +++ b/jOOQ-test/src/org/jooq/test/BaseTest.java @@ -60,6 +60,7 @@ import org.jooq.DAO; import org.jooq.DSLContext; import org.jooq.DataType; import org.jooq.ExecuteListener; +import org.jooq.ExecuteListenerProvider; import org.jooq.Field; import org.jooq.ForeignKey; import org.jooq.Record; @@ -77,8 +78,7 @@ import org.jooq.TableRecord; import org.jooq.UDTRecord; import org.jooq.UpdatableRecord; import org.jooq.conf.Settings; -import org.jooq.impl.DSL; -import org.jooq.test._.TestStatisticsListener; +import org.jooq.impl.DefaultExecuteListenerProvider; import org.jooq.test._.converters.Boolean_10; import org.jooq.test._.converters.Boolean_TF_LC; import org.jooq.test._.converters.Boolean_TF_UC; @@ -709,23 +709,19 @@ public abstract class BaseTest< } protected final DSLContext create(Settings settings) { - DSLContext create = delegate.create(settings); - addListeners(create.configuration(), new TestStatisticsListener()); - return create; + return delegate.create(settings); } protected final DSLContext create(Configuration configuration) { - DSLContext create = DSL.using(configuration); - addListeners(create.configuration(), new TestStatisticsListener()); - return create; + return delegate.create(configuration); } - protected final List getListeners(Configuration configuration) { - return delegate.getListeners(configuration); - } + protected final DSLContext create(ExecuteListener... listeners) { + ExecuteListenerProvider[] providers = new ExecuteListenerProvider[listeners.length]; + for (int i = 0; i < listeners.length; i++) + providers[i] = new DefaultExecuteListenerProvider(listeners[i]); - protected final void addListeners(Configuration configuration, ExecuteListener... listeners) { - delegate.addListeners(configuration, listeners); + return create(create().configuration().derive(providers)); } protected final Connection getConnection() { diff --git a/jOOQ-test/src/org/jooq/test/CUBRIDTest.java b/jOOQ-test/src/org/jooq/test/CUBRIDTest.java index f4ef3b651d..3c242196f0 100644 --- a/jOOQ-test/src/org/jooq/test/CUBRIDTest.java +++ b/jOOQ-test/src/org/jooq/test/CUBRIDTest.java @@ -132,7 +132,7 @@ public class CUBRIDTest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return using(getConnection(), SQLDialect.CUBRID, settings); } diff --git a/jOOQ-test/src/org/jooq/test/DB2Test.java b/jOOQ-test/src/org/jooq/test/DB2Test.java index bf68f4ab13..b4082b49f1 100644 --- a/jOOQ-test/src/org/jooq/test/DB2Test.java +++ b/jOOQ-test/src/org/jooq/test/DB2Test.java @@ -132,7 +132,7 @@ public class DB2Test extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.DB2, settings); } diff --git a/jOOQ-test/src/org/jooq/test/DerbyTest.java b/jOOQ-test/src/org/jooq/test/DerbyTest.java index 20fc284c60..ff94b00f74 100644 --- a/jOOQ-test/src/org/jooq/test/DerbyTest.java +++ b/jOOQ-test/src/org/jooq/test/DerbyTest.java @@ -132,7 +132,7 @@ public class DerbyTest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.DERBY, settings); } diff --git a/jOOQ-test/src/org/jooq/test/FirebirdTest.java b/jOOQ-test/src/org/jooq/test/FirebirdTest.java index 5a8219a9a8..144d90ab50 100644 --- a/jOOQ-test/src/org/jooq/test/FirebirdTest.java +++ b/jOOQ-test/src/org/jooq/test/FirebirdTest.java @@ -124,7 +124,7 @@ public class FirebirdTest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.FIREBIRD, settings); } diff --git a/jOOQ-test/src/org/jooq/test/H2Test.java b/jOOQ-test/src/org/jooq/test/H2Test.java index fd0de9f726..2621571558 100644 --- a/jOOQ-test/src/org/jooq/test/H2Test.java +++ b/jOOQ-test/src/org/jooq/test/H2Test.java @@ -140,7 +140,7 @@ public class H2Test extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.H2, settings); } diff --git a/jOOQ-test/src/org/jooq/test/HSQLDBTest.java b/jOOQ-test/src/org/jooq/test/HSQLDBTest.java index 9869ab927e..ee230b116f 100644 --- a/jOOQ-test/src/org/jooq/test/HSQLDBTest.java +++ b/jOOQ-test/src/org/jooq/test/HSQLDBTest.java @@ -130,7 +130,7 @@ public class HSQLDBTest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.HSQLDB, settings); } diff --git a/jOOQ-test/src/org/jooq/test/HSQLDBTest2.java b/jOOQ-test/src/org/jooq/test/HSQLDBTest2.java index 17e2ca7c95..f534e961be 100644 --- a/jOOQ-test/src/org/jooq/test/HSQLDBTest2.java +++ b/jOOQ-test/src/org/jooq/test/HSQLDBTest2.java @@ -129,7 +129,7 @@ public class HSQLDBTest2 extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { settings = (settings != null) ? settings : new Settings(); RenderMapping mapping = SettingsTools.getRenderMapping(settings); List schemata = mapping.getSchemata(); diff --git a/jOOQ-test/src/org/jooq/test/IngresTest.java b/jOOQ-test/src/org/jooq/test/IngresTest.java index a8a7841a05..ccf90abaef 100644 --- a/jOOQ-test/src/org/jooq/test/IngresTest.java +++ b/jOOQ-test/src/org/jooq/test/IngresTest.java @@ -129,7 +129,7 @@ public class IngresTest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.INGRES, settings); } diff --git a/jOOQ-test/src/org/jooq/test/MySQLTest.java b/jOOQ-test/src/org/jooq/test/MySQLTest.java index 830f371378..3cbaf4848c 100644 --- a/jOOQ-test/src/org/jooq/test/MySQLTest.java +++ b/jOOQ-test/src/org/jooq/test/MySQLTest.java @@ -158,7 +158,7 @@ public class MySQLTest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.MYSQL, settings); } diff --git a/jOOQ-test/src/org/jooq/test/MySQLTestSchemaMapping.java b/jOOQ-test/src/org/jooq/test/MySQLTestSchemaMapping.java index 5463714824..283a0977f6 100644 --- a/jOOQ-test/src/org/jooq/test/MySQLTestSchemaMapping.java +++ b/jOOQ-test/src/org/jooq/test/MySQLTestSchemaMapping.java @@ -65,7 +65,7 @@ public class MySQLTestSchemaMapping extends MySQLTest { } @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { settings = (settings != null) ? settings : new Settings(); RenderMapping mapping = SettingsTools.getRenderMapping(settings); List schemata = mapping.getSchemata(); diff --git a/jOOQ-test/src/org/jooq/test/MySQLTestSchemaRewrite.java b/jOOQ-test/src/org/jooq/test/MySQLTestSchemaRewrite.java index e56439ff3a..5dd8d9f1f8 100644 --- a/jOOQ-test/src/org/jooq/test/MySQLTestSchemaRewrite.java +++ b/jOOQ-test/src/org/jooq/test/MySQLTestSchemaRewrite.java @@ -132,7 +132,7 @@ public class MySQLTestSchemaRewrite extends jOOQAbstractTest< } @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.MYSQL, settings); } diff --git a/jOOQ-test/src/org/jooq/test/OracleTest.java b/jOOQ-test/src/org/jooq/test/OracleTest.java index 48aa023041..e9aeb50c16 100644 --- a/jOOQ-test/src/org/jooq/test/OracleTest.java +++ b/jOOQ-test/src/org/jooq/test/OracleTest.java @@ -214,7 +214,7 @@ public class OracleTest extends jOOQAbstractTest< } @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.ORACLE, settings); } diff --git a/jOOQ-test/src/org/jooq/test/OracleTestInline.java b/jOOQ-test/src/org/jooq/test/OracleTestInline.java index fb3136cdea..ceb8c8c7a2 100644 --- a/jOOQ-test/src/org/jooq/test/OracleTestInline.java +++ b/jOOQ-test/src/org/jooq/test/OracleTestInline.java @@ -49,7 +49,7 @@ import org.jooq.impl.DSL; public class OracleTestInline extends OracleTest { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { settings = (settings != null) ? settings : new Settings(); settings.withStatementType(StatementType.STATIC_STATEMENT); settings.withRenderFormatted(true); diff --git a/jOOQ-test/src/org/jooq/test/PostgresTest.java b/jOOQ-test/src/org/jooq/test/PostgresTest.java index c772ae1136..46418e81b6 100644 --- a/jOOQ-test/src/org/jooq/test/PostgresTest.java +++ b/jOOQ-test/src/org/jooq/test/PostgresTest.java @@ -148,7 +148,7 @@ public class PostgresTest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.POSTGRES, settings); } diff --git a/jOOQ-test/src/org/jooq/test/SQLServerTest.java b/jOOQ-test/src/org/jooq/test/SQLServerTest.java index d00d802298..86207e4675 100644 --- a/jOOQ-test/src/org/jooq/test/SQLServerTest.java +++ b/jOOQ-test/src/org/jooq/test/SQLServerTest.java @@ -126,7 +126,7 @@ public class SQLServerTest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.SQLSERVER, settings); } diff --git a/jOOQ-test/src/org/jooq/test/SQLServerTestInline.java b/jOOQ-test/src/org/jooq/test/SQLServerTestInline.java index 2c02d4d463..8749101b00 100644 --- a/jOOQ-test/src/org/jooq/test/SQLServerTestInline.java +++ b/jOOQ-test/src/org/jooq/test/SQLServerTestInline.java @@ -49,7 +49,7 @@ import org.jooq.impl.DSL; public class SQLServerTestInline extends SQLServerTest { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { settings = (settings != null) ? settings : new Settings(); settings.withStatementType(StatementType.STATIC_STATEMENT); return DSL.using(getConnection(), SQLDialect.SQLSERVER, settings); diff --git a/jOOQ-test/src/org/jooq/test/SQLiteTest.java b/jOOQ-test/src/org/jooq/test/SQLiteTest.java index 45d28ad234..c501a325bb 100644 --- a/jOOQ-test/src/org/jooq/test/SQLiteTest.java +++ b/jOOQ-test/src/org/jooq/test/SQLiteTest.java @@ -126,7 +126,7 @@ public class SQLiteTest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.SQLITE, settings); } diff --git a/jOOQ-test/src/org/jooq/test/SybaseTest.java b/jOOQ-test/src/org/jooq/test/SybaseTest.java index 0461cc8fc6..609c51bc9e 100644 --- a/jOOQ-test/src/org/jooq/test/SybaseTest.java +++ b/jOOQ-test/src/org/jooq/test/SybaseTest.java @@ -126,7 +126,7 @@ public class SybaseTest extends jOOQAbstractTest< T_785Record> { @Override - protected DSLContext create(Settings settings) { + protected DSLContext create0(Settings settings) { return DSL.using(getConnection(), SQLDialect.SYBASE, settings); } diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/BenchmarkTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/BenchmarkTests.java index 406b9ae4c1..698aab0620 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/BenchmarkTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/BenchmarkTests.java @@ -42,6 +42,7 @@ import java.util.Random; import org.jooq.Configuration; import org.jooq.DSLContext; +import org.jooq.ExecuteListenerProvider; import org.jooq.Record1; import org.jooq.Record2; import org.jooq.Record3; @@ -126,9 +127,8 @@ extends BaseTest cLibrary(); protected abstract Class cSequences(); protected abstract DataType[] getCastableDataTypes(); - protected abstract DSLContext create(Settings settings); + protected abstract DSLContext create0(Settings settings); protected final Schema schema() { return create().map(TAuthor().getSchema()); @@ -875,25 +876,42 @@ public abstract class jOOQAbstractTest< .withRenderMapping(new RenderMapping() .withDefaultSchema(defaultSchema)); - DSLContext create = create(settings); - addListeners(create.configuration(), - new TestStatisticsListener(), - new PrettyPrinter(), - new LifecycleWatcherListener()); - - return create; + return DSL.using(create0(settings).configuration().derive( + DefaultExecuteListenerProvider.providers( + new TestStatisticsListener(), + new PrettyPrinter(), + new LifecycleWatcherListener() + ) + )); } - protected final List getListeners(org.jooq.Configuration configuration) { - - // Most test cases run with the DefaultExecuteListenerProvider, - // which (inofficially) exposes a mutable List - DefaultExecuteListenerProvider provider = (DefaultExecuteListenerProvider) configuration.executeListenerProvider(); - return provider.provide(); + protected final DSLContext create(Settings settings) { + DSLContext create = create0(settings); + return create(create.configuration()); } - protected final void addListeners(org.jooq.Configuration configuration, ExecuteListener... listeners) { - getListeners(configuration).addAll(Arrays.asList(listeners)); + protected final DSLContext create(org.jooq.Configuration configuration) { + return DSL.using(configuration.derive(combine( + configuration.executeListenerProviders(), + new DefaultExecuteListenerProvider(new TestStatisticsListener()) + ))); + } + + protected final DSLContext create(ExecuteListener... listeners) { + ExecuteListenerProvider[] providers = new ExecuteListenerProvider[listeners.length]; + for (int i = 0; i < listeners.length; i++) + providers[i] = new DefaultExecuteListenerProvider(listeners[i]); + + return create(create().configuration().derive(providers)); + } + + protected static final T[] combine(T[] array, T value) { + T[] result = (T[]) java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), array.length + 1); + + System.arraycopy(array, 0, result, 0, array.length); + result[array.length] = value; + + return result; } protected final SQLDialect getDialect() { diff --git a/jOOQ/src/main/java/org/jooq/Configuration.java b/jOOQ/src/main/java/org/jooq/Configuration.java index 9676ebbf35..c0d158a790 100644 --- a/jOOQ/src/main/java/org/jooq/Configuration.java +++ b/jOOQ/src/main/java/org/jooq/Configuration.java @@ -172,7 +172,7 @@ public interface Configuration extends Serializable { * @see ExecuteListener * @see ExecuteContext */ - ExecuteListenerProvider executeListenerProvider(); + ExecuteListenerProvider[] executeListenerProviders(); /** * Create a derived configuration from this one, without changing any @@ -218,6 +218,6 @@ public interface Configuration extends Serializable { * contained in the derived configuration. * @return The derived configuration. */ - Configuration derive(ExecuteListenerProvider newExecuteListenerProvider); + Configuration derive(ExecuteListenerProvider... newExecuteListenerProviders); } diff --git a/jOOQ/src/main/java/org/jooq/ExecuteListenerProvider.java b/jOOQ/src/main/java/org/jooq/ExecuteListenerProvider.java index 33368eab74..fb0cab3655 100644 --- a/jOOQ/src/main/java/org/jooq/ExecuteListenerProvider.java +++ b/jOOQ/src/main/java/org/jooq/ExecuteListenerProvider.java @@ -35,15 +35,11 @@ */ package org.jooq; -import java.util.List; +import org.jooq.impl.DefaultExecuteListenerProvider; /** * A provider for {@link ExecuteListener} instances. *

- * WARNING: The design of the ExecuteListener API is - * undergoing change and may be unstable at the current stage of jOOQ 3.0-RC3 - * development. USE AT OWN RISK! - *

* In order to facilitate the lifecycle management of * ExecuteListener instances that are provided to a jOOQ * {@link Configuration}, clients can implement this API. To jOOQ, it is thus @@ -57,13 +53,19 @@ import java.util.List; public interface ExecuteListenerProvider { /** - * Provide a list of ExecuteListener instances. + * Provide an ExecuteListener instance. *

- * jOOQ will issue {@link ExecuteListener} notification events to each - * listener in the order of iteration of the returned list. + * Implementations are free to choose whether this method returns new + * instances at every call or whether the same instance is returned + * repetitively. + *

+ * An ExecuteListener shall be provided exactly once per query + * execution lifecycle, i.e. per ExecuteContext. * - * @return A list of ExecuteListener instances. + * @return An ExecuteListener instance. * @see ExecuteListener + * @see ExecuteContext + * @see DefaultExecuteListenerProvider */ - List provide(); + ExecuteListener provide(); } diff --git a/jOOQ/src/main/java/org/jooq/impl/BatchCRUD.java b/jOOQ/src/main/java/org/jooq/impl/BatchCRUD.java index 50e8558fa5..8356fe2fb3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/BatchCRUD.java +++ b/jOOQ/src/main/java/org/jooq/impl/BatchCRUD.java @@ -49,7 +49,6 @@ import org.jooq.BatchBindStep; import org.jooq.Configuration; import org.jooq.DSLContext; import org.jooq.ExecuteContext; -import org.jooq.ExecuteListener; import org.jooq.Query; import org.jooq.UpdatableRecord; import org.jooq.exception.DataAccessException; @@ -99,9 +98,10 @@ class BatchCRUD implements Batch { QueryCollector collector = new QueryCollector(); // Add the QueryCollector to intercept query execution after rendering - List listeners = new ArrayList(configuration.executeListenerProvider().provide()); - listeners.add(collector); - Configuration local = configuration.derive(new DefaultExecuteListenerProvider(listeners)); + Configuration local = configuration.derive(Utils.combine( + configuration.executeListenerProviders(), + new DefaultExecuteListenerProvider(collector) + )); // [#1537] Communicate with UpdatableRecordImpl local.data(Utils.DATA_OMIT_RETURNING_CLAUSE, true); @@ -167,9 +167,10 @@ class BatchCRUD implements Batch { List queries = new ArrayList(); QueryCollector collector = new QueryCollector(); - List listeners = new ArrayList(configuration.executeListenerProvider().provide()); - listeners.add(collector); - Configuration local = configuration.derive(new DefaultExecuteListenerProvider(listeners)); + Configuration local = configuration.derive(Utils.combine( + configuration.executeListenerProviders(), + new DefaultExecuteListenerProvider(collector) + )); for (int i = 0; i < records.length; i++) { Configuration previous = ((AttachableInternal) records[i]).configuration(); diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultConfiguration.java b/jOOQ/src/main/java/org/jooq/impl/DefaultConfiguration.java index 3670b08d56..fcc4ff2f56 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultConfiguration.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultConfiguration.java @@ -78,7 +78,7 @@ public class DefaultConfiguration implements Configuration { // Non-serializable Configuration objects private transient ConnectionProvider connectionProvider; - private transient ExecuteListenerProvider listenerProvider; + private transient ExecuteListenerProvider[] listenerProviders; // Derived objects private final org.jooq.SchemaMapping mapping; @@ -97,7 +97,7 @@ public class DefaultConfiguration implements Configuration { public DefaultConfiguration() { this( new NoConnectionProvider(), - new DefaultExecuteListenerProvider(), + new ExecuteListenerProvider[0], SQL99, SettingsTools.defaultSettings(), null); @@ -114,7 +114,7 @@ public class DefaultConfiguration implements Configuration { DefaultConfiguration(Configuration configuration) { this( configuration.connectionProvider(), - configuration.executeListenerProvider(), + configuration.executeListenerProviders(), configuration.dialect(), configuration.settings(), configuration.data() @@ -131,15 +131,15 @@ public class DefaultConfiguration implements Configuration { */ DefaultConfiguration( ConnectionProvider connectionProvider, - ExecuteListenerProvider listenerProvider, + ExecuteListenerProvider[] listenerProviders, SQLDialect dialect, Settings settings, Map data) { this.connectionProvider = connectionProvider; - this.listenerProvider = listenerProvider != null - ? listenerProvider - : new DefaultExecuteListenerProvider(); + this.listenerProviders = listenerProviders != null + ? listenerProviders + : new ExecuteListenerProvider[0]; this.dialect = dialect; this.settings = settings != null @@ -170,7 +170,7 @@ public class DefaultConfiguration implements Configuration { */ @Override public final Configuration derive(SQLDialect newDialect) { - return new DefaultConfiguration(connectionProvider, listenerProvider, newDialect, settings, data); + return new DefaultConfiguration(connectionProvider, listenerProviders, newDialect, settings, data); } /** @@ -178,7 +178,7 @@ public class DefaultConfiguration implements Configuration { */ @Override public final Configuration derive(ConnectionProvider newConnectionProvider) { - return new DefaultConfiguration(newConnectionProvider, listenerProvider, dialect, settings, data); + return new DefaultConfiguration(newConnectionProvider, listenerProviders, dialect, settings, data); } /** @@ -186,15 +186,15 @@ public class DefaultConfiguration implements Configuration { */ @Override public final Configuration derive(Settings newSettings) { - return new DefaultConfiguration(connectionProvider, listenerProvider, dialect, newSettings, data); + return new DefaultConfiguration(connectionProvider, listenerProviders, dialect, newSettings, data); } /** * {@inheritDoc} */ @Override - public final Configuration derive(ExecuteListenerProvider newExecuteListenerProvider) { - return new DefaultConfiguration(connectionProvider, newExecuteListenerProvider, dialect, settings, data); + public final Configuration derive(ExecuteListenerProvider... newExecuteListenerProviders) { + return new DefaultConfiguration(connectionProvider, newExecuteListenerProviders, dialect, settings, data); } // ------------------------------------------------------------------------- @@ -262,8 +262,8 @@ public class DefaultConfiguration implements Configuration { * {@inheritDoc} */ @Override - public final ExecuteListenerProvider executeListenerProvider() { - return listenerProvider; + public final ExecuteListenerProvider[] executeListenerProviders() { + return listenerProviders; } @Override @@ -289,15 +289,21 @@ public class DefaultConfiguration implements Configuration { oos.writeObject(connectionProvider instanceof Serializable ? connectionProvider : null); - oos.writeObject(listenerProvider instanceof Serializable - ? listenerProvider - : null); + + ExecuteListenerProvider[] clone = new ExecuteListenerProvider[listenerProviders.length]; + for (int i = 0; i < clone.length; i++) { + if (listenerProviders[i] instanceof Serializable) { + clone[i] = listenerProviders[i]; + } + } + + oos.writeObject(clone); } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); connectionProvider = (ConnectionProvider) ois.readObject(); - listenerProvider = (ExecuteListenerProvider) ois.readObject(); + listenerProviders = (ExecuteListenerProvider[]) ois.readObject(); } } \ No newline at end of file diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteListenerProvider.java b/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteListenerProvider.java index e9d7b450ae..53e3cbc602 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteListenerProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteListenerProvider.java @@ -36,9 +36,6 @@ package org.jooq.impl; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import org.jooq.ExecuteListener; import org.jooq.ExecuteListenerProvider; @@ -46,9 +43,9 @@ import org.jooq.ExecuteListenerProvider; /** * A default implementation for {@link ExecuteListenerProvider}. *

- * This implementation just wraps a List of {@link ExecuteListener} - * instances, always providing the same. - * + * This implementation just wraps an instance of {@link ExecuteListener}, always + * providing the same. + * * @author Lukas Eder */ public class DefaultExecuteListenerProvider implements ExecuteListenerProvider, Serializable { @@ -61,40 +58,38 @@ public class DefaultExecuteListenerProvider implements ExecuteListenerProvider, /** * The delegate list. */ - private List listeners; + private final ExecuteListener listener; /** - * Create a new provider instance with an empty ArrayList - * argument. + * Convenience method to construct an array of + * DefaultExecuteListenerProvider from an array of + * ExecuteListener instances. */ - public DefaultExecuteListenerProvider() { - this(new ArrayList()); + public static ExecuteListenerProvider[] providers(ExecuteListener... listeners) { + ExecuteListenerProvider[] result = new ExecuteListenerProvider[listeners.length]; + + for (int i = 0; i < listeners.length; i++) { + result[i] = new DefaultExecuteListenerProvider(listeners[i]); + } + + return result; } /** - * Create a new provider instance from an argument List. + * Create a new provider instance from an argument listener. * - * @param listeners The argument list. + * @param listener The argument listener. */ - public DefaultExecuteListenerProvider(ExecuteListener... listeners) { - this.listeners = new ArrayList(Arrays.asList(listeners)); - } - - /** - * Create a new provider instance from an argument List. - * - * @param listeners The argument list. - */ - public DefaultExecuteListenerProvider(List listeners) { - this.listeners = listeners; + public DefaultExecuteListenerProvider(ExecuteListener listener) { + this.listener = listener; } /** * {@inheritDoc} */ @Override - public final List provide() { - return listeners; + public final ExecuteListener provide() { + return listener; } /** @@ -102,6 +97,6 @@ public class DefaultExecuteListenerProvider implements ExecuteListenerProvider, */ @Override public String toString() { - return "" + listeners; + return listener.toString(); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/ExecuteListeners.java b/jOOQ/src/main/java/org/jooq/impl/ExecuteListeners.java index 8b5894cc85..321974b8d6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ExecuteListeners.java +++ b/jOOQ/src/main/java/org/jooq/impl/ExecuteListeners.java @@ -35,11 +35,17 @@ */ package org.jooq.impl; +import static java.lang.Boolean.FALSE; + +import java.util.ArrayList; import java.util.List; import org.jooq.ExecuteContext; import org.jooq.ExecuteListener; +import org.jooq.ExecuteListenerProvider; import org.jooq.conf.Settings; +import org.jooq.tools.LoggerListener; +import org.jooq.tools.StopWatchListener; /** * A queue implementation for several {@link ExecuteListener} objects as defined @@ -52,7 +58,7 @@ class ExecuteListeners implements ExecuteListener { /** * Generated UID */ - private static final long serialVersionUID = 7399239846062763212L; + private static final long serialVersionUID = 7399239846062763212L; private final List listeners; @@ -63,11 +69,33 @@ class ExecuteListeners implements ExecuteListener { private boolean fetchEnd; ExecuteListeners(ExecuteContext ctx) { - listeners = Utils.getListeners(ctx); + listeners = listeners(ctx); start(ctx); } + /** + * Provide delegate listeners from an ExecuteContext + */ + private static List listeners(ExecuteContext ctx) { + List result = new ArrayList(); + + if (!FALSE.equals(ctx.configuration().settings().isExecuteLogging())) { + result.add(new StopWatchListener()); + result.add(new LoggerListener()); + } + + for (ExecuteListenerProvider provider : ctx.configuration().executeListenerProviders()) { + + // Could be null after deserialisation + if (provider != null) { + result.add(provider.provide()); + } + } + + return result; + } + @Override public final void start(ExecuteContext ctx) { for (ExecuteListener listener : listeners) { diff --git a/jOOQ/src/main/java/org/jooq/impl/Utils.java b/jOOQ/src/main/java/org/jooq/impl/Utils.java index d9cc343728..eea0df0903 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Utils.java +++ b/jOOQ/src/main/java/org/jooq/impl/Utils.java @@ -956,6 +956,16 @@ final class Utils { } } + @SuppressWarnings("unchecked") + static final T[] combine(T[] array, T value) { + T[] result = (T[]) java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), array.length + 1); + + System.arraycopy(array, 0, result, 0, array.length); + result[array.length] = value; + + return result; + } + /** * Combine a field with an array of fields */ @@ -1090,25 +1100,6 @@ final class Utils { } } - /** - * Get a list of ExecuteListener instances (including defaults) from a - * configuration - */ - static final List getListeners(ExecuteContext ctx) { - List result = new ArrayList(); - if (!FALSE.equals(ctx.configuration().settings().isExecuteLogging())) { - result.add(new StopWatchListener()); - result.add(new LoggerListener()); - } - - ExecuteListenerProvider provider = ctx.configuration().executeListenerProvider(); - if (provider != null) { - result.addAll(provider.provide()); - } - - return result; - } - /** * Wrap a piece of SQL code in parentheses, if not wrapped already */