From f252b80c2dbaf2e6b51591b72a3a5c0357492734 Mon Sep 17 00:00:00 2001 From: Robin Bygrave Date: Mon, 7 Dec 2015 22:13:27 +1300 Subject: [PATCH] #476 - ENH: Enable ServiceConfig to use alternate ClassLoader - was ServiceConfig add setClassloader api --- part 3: Refactor with ClassLoadConfig --- .../avaje/ebean/config/ClassLoadConfig.java | 143 +++++++++++++++++ .../com/avaje/ebean/config/ServerConfig.java | 24 ++- .../ebeaninternal/api/ClassLoadContext.java | 146 ------------------ .../avaje/ebeaninternal/api/ClassUtil.java | 105 ++++++------- .../server/core/DefaultContainer.java | 13 +- .../server/core/InternalConfiguration.java | 2 +- .../deploy/BeanPropertyAssocManyJsonHelp.java | 5 +- .../GeneratedPropertyFactory.java | 21 ++- .../InsertTimestampFactory.java | 10 +- .../UpdateTimestampFactory.java | 8 +- .../server/deploy/parse/ReadAnnotations.java | 5 +- .../server/lib/sql/DataSourcePool.java | 20 +-- .../server/type/DefaultTypeManager.java | 12 +- .../server/util/ClassPathSearch.java | 2 +- .../InsertTimestampFactoryTest.java | 3 +- .../UpdateTimestampFactoryTest.java | 3 +- 16 files changed, 266 insertions(+), 256 deletions(-) create mode 100644 src/main/java/com/avaje/ebean/config/ClassLoadConfig.java delete mode 100644 src/main/java/com/avaje/ebeaninternal/api/ClassLoadContext.java diff --git a/src/main/java/com/avaje/ebean/config/ClassLoadConfig.java b/src/main/java/com/avaje/ebean/config/ClassLoadConfig.java new file mode 100644 index 000000000..ca0a75c74 --- /dev/null +++ b/src/main/java/com/avaje/ebean/config/ClassLoadConfig.java @@ -0,0 +1,143 @@ +package com.avaje.ebean.config; + + +/** + * Helper to find classes taking into account the context class loader. + */ +public class ClassLoadConfig { + + protected final ClassLoaderContext context; + + /** + * Construct with the default classLoader search with context classLoader first. + */ + public ClassLoadConfig() { + this(null); + } + + /** + * Specify the classLoader to use for class detection and new instance creation. + */ + public ClassLoadConfig(ClassLoader classLoader) { + this.context = new ClassLoaderContext(classLoader); + } + + /** + * Return true if the Java.time types are available and should be supported. + */ + public boolean isJavaTimePresent() { + return isPresent("java.time.LocalDate"); + } + + /** + * Return true if the Joda types are available and should be supported. + */ + public boolean isJodaTimePresent() { + return isPresent("org.joda.time.LocalDateTime"); + } + + /** + * Return true if javax validation annotations like Size and NotNull are present. + */ + public boolean isJavaxValidationAnnotationsPresent() { + return isPresent("javax.validation.constraints.NotNull"); + } + + /** + * Return true if Jackson annotations like JsonIgnore are present. + */ + public boolean isJacksonAnnotationsPresent() { + return isPresent("com.fasterxml.jackson.annotation.JsonIgnore"); + } + + /** + * Return true if Jackson ObjectMapper is present. + */ + public boolean isJacksonObjectMapperPresent() { + return isPresent("com.fasterxml.jackson.databind.ObjectMapper"); + } + + /** + * Return a new instance of the class using the default constructor. + */ + public Object newInstance(String className) { + + try { + Class cls = forName(className); + return cls.newInstance(); + } catch (Exception e) { + throw new IllegalArgumentException("Error constructing " + className, e); + } + } + + /** + * Return true if the given class is present. + */ + protected boolean isPresent(String className) { + try { + forName(className); + return true; + } catch (Throwable ex) { + // Class or one of its dependencies is not present... + return false; + } + } + + /** + * Load a class taking into account a context class loader (if present). + */ + protected Class forName(String name) throws ClassNotFoundException { + return context.forName(name); + } + + /** + * Wraps the preferred, caller and context class loaders. + */ + protected class ClassLoaderContext { + + /** + * Optional - if set only use this classLoader (no fallback). + */ + protected final ClassLoader preferredLoader; + + protected final ClassLoader contextLoader; + + protected final ClassLoader callerLoader; + + ClassLoaderContext(ClassLoader preferredLoader) { + this.preferredLoader = preferredLoader; + this.callerLoader = ServerConfig.class.getClassLoader(); + this.contextLoader = contextLoader(); + } + + ClassLoader contextLoader() { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + return (loader != null) ? loader: callerLoader; + } + + Class forName(String name) throws ClassNotFoundException { + + if (preferredLoader != null) { + // only use the explicitly set classLoader + return classForName(name, preferredLoader); + } + try { + // try the context loader first + return classForName(name, contextLoader); + } catch (ClassNotFoundException e) { + if (callerLoader == contextLoader) { + throw e; + } else { + // fallback to the caller classLoader + return classForName(name, callerLoader); + } + } + } + + Class classForName(String name, ClassLoader classLoader) throws ClassNotFoundException { + return Class.forName(name, true, classLoader); + } + + } +} + diff --git a/src/main/java/com/avaje/ebean/config/ServerConfig.java b/src/main/java/com/avaje/ebean/config/ServerConfig.java index 546883eb7..ff255ffbe 100644 --- a/src/main/java/com/avaje/ebean/config/ServerConfig.java +++ b/src/main/java/com/avaje/ebean/config/ServerConfig.java @@ -21,7 +21,6 @@ import com.avaje.ebean.event.changelog.ChangeLogRegister; import com.avaje.ebean.event.readaudit.ReadAuditLogger; import com.avaje.ebean.event.readaudit.ReadAuditPrepare; import com.avaje.ebean.meta.MetaInfoManager; -import com.avaje.ebeaninternal.api.ClassUtil; import com.fasterxml.jackson.core.JsonFactory; import javax.sql.DataSource; @@ -235,6 +234,11 @@ public class ServerConfig { */ private DbMigrationConfig migrationConfig = new DbMigrationConfig(); + /** + * The ClassLoadConfig used to detect Joda, Java8, Jackson etc and create plugin instances given a className. + */ + private ClassLoadConfig classLoadConfig = new ClassLoadConfig(); + /** * Set to true if the DataSource uses autoCommit. *

@@ -2030,6 +2034,22 @@ public class ServerConfig { this.persistenceContextScope = persistenceContextScope; } + /** + * Return the ClassLoadConfig which is used to detect Joda, Java8 types etc and also + * create new instances of plugins given a className. + */ + public ClassLoadConfig getClassLoadConfig() { + return classLoadConfig; + } + + /** + * Set the ClassLoadConfig which is used to detect Joda, Java8 types etc and also + * create new instances of plugins given a className. + */ + public void setClassLoadConfig(ClassLoadConfig classLoadConfig) { + this.classLoadConfig = classLoadConfig; + } + /** * Load settings from ebean.properties. */ @@ -2093,7 +2113,7 @@ public class ServerConfig { * @param classname the implementation class as per properties */ protected T createInstance(Class pluginType, String classname) { - return classname == null ? null : (T) ClassUtil.newInstance(classname); + return classname == null ? null : (T) classLoadConfig.newInstance(classname); } /** diff --git a/src/main/java/com/avaje/ebeaninternal/api/ClassLoadContext.java b/src/main/java/com/avaje/ebeaninternal/api/ClassLoadContext.java deleted file mode 100644 index e0666d9b7..000000000 --- a/src/main/java/com/avaje/ebeaninternal/api/ClassLoadContext.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.avaje.ebeaninternal.api; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Wraps the caller and context class loaders. - *

- * Helper for ClassUtil. - *

- * - * @author rbygrave - */ -class ClassLoadContext { - - private static final Logger logger = LoggerFactory.getLogger(ClassLoadContext.class); - - private final ClassLoader callerLoader; - - private final ClassLoader contextLoader; - - private final boolean preferContext; - - private boolean ambiguous; - - public static ClassLoadContext of(Class caller, boolean preferContext) { - return new ClassLoadContext(caller, preferContext); - } - - /** - * This constructor is package-private to restrict instantiation to - */ - ClassLoadContext(final Class caller, boolean preferContext) { - if (caller == null) { - throw new IllegalArgumentException("caller is null"); - } - this.callerLoader = caller.getClassLoader(); - this.contextLoader = Thread.currentThread().getContextClassLoader(); - this.preferContext = preferContext; - } - - public Class forName(String name) throws ClassNotFoundException { - - ClassLoader defaultLoader = getDefault(preferContext); - - try { - return Class.forName(name, true, defaultLoader); - } catch (ClassNotFoundException e) { - if (callerLoader == defaultLoader) { - throw e; - } else { - return Class.forName(name, true, callerLoader); - } - } - } - - - /** - * Return the expected class loader to use. - *

- * Works on the assumption that the child of the caller or context class - * loader is preferred. - *

- */ - public ClassLoader getDefault(boolean preferContext) { - - if (contextLoader == null) { - if (logger.isDebugEnabled()) { - logger.debug("No Context ClassLoader, using " + callerLoader.getClass().getName()); - } - return callerLoader; - } - if (contextLoader == callerLoader) { - if (logger.isDebugEnabled()) { - logger.debug("Context and Caller ClassLoader's same instance of " + contextLoader.getClass().getName()); - } - return callerLoader; - } - - if (isChild(contextLoader, callerLoader)) { - if (logger.isDebugEnabled()) { - logger.debug("Caller ClassLoader " + callerLoader.getClass().getName() - + " child of ContextLoader " + contextLoader.getClass().getName()); - } - return callerLoader; - - } else if (isChild(callerLoader, contextLoader)) { - if (logger.isDebugEnabled()) { - logger.debug("Context ClassLoader " + contextLoader.getClass().getName() - + " child of Caller ClassLoader " + callerLoader.getClass().getName()); - } - return contextLoader; - - } else { - // ambiguous case, perhaps both null - logger.debug("Ambiguous ClassLoader choice preferContext:" + preferContext - + " Context:" + contextLoader.getClass().getName() + " Caller:" + callerLoader.getClass().getName()); - ambiguous = true; - return preferContext ? contextLoader : callerLoader; - } - } - - /** - * Return true if the 'default' class loader is ambiguous. - */ - public boolean isAmbiguous() { - return ambiguous; - } - - /** - * Return the ClassLoader of the caller. - */ - public ClassLoader getCallerLoader() { - return callerLoader; - } - - /** - * Return the Thread Context ClassLoader. - */ - public ClassLoader getContextLoader() { - return contextLoader; - } - - /** - * Return the ClassLoader for this class. - */ - public ClassLoader getThisLoader() { - return this.getClass().getClassLoader(); - } - - /** - * Returns 'true' if 'loader2' is a delegation child of 'loader1' [or if - * 'loader1'=='loader2']. - */ - private boolean isChild(final ClassLoader loader1, ClassLoader loader2) { - - for (; loader2 != null; loader2 = loader2.getParent()) { - if (loader2 == loader1) { - return true; - } - } - - return false; - } - -} \ No newline at end of file diff --git a/src/main/java/com/avaje/ebeaninternal/api/ClassUtil.java b/src/main/java/com/avaje/ebeaninternal/api/ClassUtil.java index b5b9d66d0..380abe714 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/ClassUtil.java +++ b/src/main/java/com/avaje/ebeaninternal/api/ClassUtil.java @@ -6,79 +6,60 @@ package com.avaje.ebeaninternal.api; */ public class ClassUtil { - /** - * Load a class taking into account a context class loader (if present). - */ - public static Class forName(String name, Class caller) throws ClassNotFoundException { - - if (caller == null) { - caller = ClassUtil.class; - } - ClassLoadContext ctx = ClassLoadContext.of(caller, true); - return ctx.forName(name); - } - - /** - * Return true if javax validation annotations like Size and NotNull are present. - */ - public static boolean isJavaxValidationAnnotationsPresent() { - return isPresent("javax.validation.constraints.NotNull", null); - } - - /** - * Return true if Jackson annotations like JsonIgnore are present. - */ - public static boolean isJacksonAnnotationsPresent() { - return isPresent("com.fasterxml.jackson.annotation.JsonIgnore", null); - } - - /** - * Return true if Jackson ObjectMapper is present. - */ - public static boolean isJacksonObjectMapperPresent() { - return isPresent("com.fasterxml.jackson.databind.ObjectMapper", null); - } - - - /** - * Return true if the given class is present. - */ - public static boolean isPresent(String className) { - return isPresent(className, null); - } - - /** - * Return true if the given class is present. - */ - public static boolean isPresent(String className, Class caller) { - try { - forName(className, caller); - return true; - } catch (Throwable ex) { - // Class or one of its dependencies is not present... - return false; - } - } - /** * Return a new instance of the class using the default constructor. */ public static Object newInstance(String className) { - return newInstance(className, null); - } - - /** - * Return a new instance of the class using the default constructor. - */ - public static Object newInstance(String className, Class caller) { try { - Class cls = forName(className, caller); + Class cls = forName(className); return cls.newInstance(); } catch (Exception e) { String msg = "Error constructing " + className; throw new IllegalArgumentException(msg, e); } } + + /** + * Load a class taking into account a context class loader (if present). + */ + private static Class forName(String name) throws ClassNotFoundException { + return new ClassLoadContext().forName(name); + } + + + /** + * Helper to wrap the context and caller classLoaders (to use/try both). + */ + static class ClassLoadContext { + + private final ClassLoader contextLoader; + + private final ClassLoader callerLoader; + + ClassLoadContext() { + this.callerLoader = ClassUtil.class.getClassLoader(); + this.contextLoader = contextLoader(); + } + + ClassLoader contextLoader() { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + return (loader != null) ? loader: callerLoader; + } + + public Class forName(String name) throws ClassNotFoundException { + + try { + return Class.forName(name, true, contextLoader); + } catch (ClassNotFoundException e) { + if (callerLoader == contextLoader) { + throw e; + } else { + return Class.forName(name, true, callerLoader); + } + } + } + + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java index 9ce4609d3..12b3be352 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultContainer.java @@ -20,6 +20,7 @@ import com.avaje.ebeaninternal.server.cluster.ClusterManager; import com.avaje.ebeaninternal.server.lib.ShutdownManager; import com.avaje.ebeaninternal.server.lib.sql.DataSourceAlert; import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool; +import com.avaje.ebeaninternal.server.lib.sql.DataSourcePoolListener; import com.avaje.ebeaninternal.server.lib.sql.SimpleDataSourceAlert; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -311,7 +312,17 @@ public class DefaultContainer implements SpiContainer { } DataSourceAlert notify = new SimpleDataSourceAlert(); - return new DataSourcePool(notify, config.getName(), dsConfig); + DataSourcePoolListener listener = createListener(config, dsConfig); + + return new DataSourcePool(notify, config.getName(), dsConfig, listener); + } + + /** + * Create and return a DataSourcePoolListener if it has been specified. + */ + private DataSourcePoolListener createListener(ServerConfig config, DataSourceConfig dsConfig) { + String poolListener = dsConfig.getPoolListener(); + return poolListener != null ? (DataSourcePoolListener) config.getClassLoadConfig().newInstance(poolListener) : null; } /** diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java b/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java index cee293377..1eff41bc6 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java @@ -357,6 +357,6 @@ public class InternalConfiguration { } public GeneratedPropertyFactory getGeneratedPropertyFactory() { - return new GeneratedPropertyFactory(serverConfig.getCurrentUserProvider()); + return new GeneratedPropertyFactory(serverConfig); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java index e6d30d68f..3ed83be20 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java @@ -31,7 +31,7 @@ public class BeanPropertyAssocManyJsonHelp { */ public BeanPropertyAssocManyJsonHelp(BeanPropertyAssocMany many) { this.many = many; - this.jsonTransient = !ClassUtil.isJacksonObjectMapperPresent() ? null : new BeanPropertyAssocManyJsonTransient(); + this.jsonTransient = new BeanPropertyAssocManyJsonTransient(); } /** @@ -81,9 +81,6 @@ public class BeanPropertyAssocManyJsonHelp { */ private void jsonReadTransientUsingObjectMapper(ReadJson readJson, EntityBean parentBean) throws IOException { - if (jsonTransient == null) { - throw new IllegalStateException("Jackson ObjectMapper is required to read this Transient property "+many.getFullBeanName()); - } jsonTransient.jsonReadUsingObjectMapper(many, readJson, parentBean); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/GeneratedPropertyFactory.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/GeneratedPropertyFactory.java index db33ffe8e..5810f61ee 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/GeneratedPropertyFactory.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/GeneratedPropertyFactory.java @@ -3,7 +3,9 @@ package com.avaje.ebeaninternal.server.deploy.generatedproperty; import java.math.BigDecimal; import java.util.HashSet; +import com.avaje.ebean.config.ClassLoadConfig; import com.avaje.ebean.config.CurrentUserProvider; +import com.avaje.ebean.config.ServerConfig; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty; /** @@ -13,9 +15,9 @@ public class GeneratedPropertyFactory { private final CounterFactory counterFactory = new CounterFactory(); - private final InsertTimestampFactory insertFactory = new InsertTimestampFactory(); + private final InsertTimestampFactory insertFactory; - private final UpdateTimestampFactory updateFactory = new UpdateTimestampFactory(); + private final UpdateTimestampFactory updateFactory; private final HashSet numberTypes = new HashSet(); @@ -23,8 +25,15 @@ public class GeneratedPropertyFactory { private final GeneratedWhoCreated generatedWhoCreated; - public GeneratedPropertyFactory(CurrentUserProvider currentUserProvider) { + private final ClassLoadConfig classLoadConfig; + public GeneratedPropertyFactory(ServerConfig serverConfig) { + + this.classLoadConfig = serverConfig.getClassLoadConfig(); + this.insertFactory = new InsertTimestampFactory(classLoadConfig); + this.updateFactory = new UpdateTimestampFactory(classLoadConfig); + + CurrentUserProvider currentUserProvider = serverConfig.getCurrentUserProvider(); if (currentUserProvider != null) { generatedWhoCreated = new GeneratedWhoCreated(currentUserProvider); generatedWhoModified = new GeneratedWhoModified(currentUserProvider); @@ -44,7 +53,11 @@ public class GeneratedPropertyFactory { numberTypes.add(BigDecimal.class.getName()); } - private boolean isNumberType(String typeClassName) { + public ClassLoadConfig getClassLoadConfig() { + return classLoadConfig; + } + + private boolean isNumberType(String typeClassName) { return numberTypes.contains(typeClassName); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/InsertTimestampFactory.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/InsertTimestampFactory.java index fe9c5b37b..c9866f42e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/InsertTimestampFactory.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/InsertTimestampFactory.java @@ -9,7 +9,7 @@ import java.util.Map; import javax.persistence.PersistenceException; -import com.avaje.ebeaninternal.api.ClassUtil; +import com.avaje.ebean.config.ClassLoadConfig; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty; /** @@ -21,25 +21,25 @@ public class InsertTimestampFactory { final Map, GeneratedProperty> map = new HashMap, GeneratedProperty>(); - public InsertTimestampFactory() { + public InsertTimestampFactory(ClassLoadConfig classLoadConfig) { map.put(Timestamp.class, new GeneratedInsertTimestamp()); map.put(java.util.Date.class, new GeneratedInsertDate()); map.put(Long.class, longTime); map.put(long.class, longTime); - if (ClassUtil.isPresent("java.time.LocalDate", this.getClass())) { + if (classLoadConfig.isJavaTimePresent()) { map.put(LocalDateTime.class, new GeneratedInsertJavaTime.LocalDT()); map.put(OffsetDateTime.class, new GeneratedInsertJavaTime.OffsetDT()); map.put(ZonedDateTime.class, new GeneratedInsertJavaTime.ZonedDT()); } - if (ClassUtil.isPresent("org.joda.time.LocalDateTime", this.getClass())) { + if (classLoadConfig.isJodaTimePresent()) { map.put(org.joda.time.LocalDateTime.class, new GeneratedInsertJodaTime.LocalDT()); map.put(org.joda.time.DateTime.class, new GeneratedInsertJodaTime.DateTimeDT()); } } - public void setInsertTimestamp(DeployBeanProperty property) { + public void setInsertTimestamp(DeployBeanProperty property) { property.setGeneratedProperty(createInsertTimestamp(property)); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/UpdateTimestampFactory.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/UpdateTimestampFactory.java index 979352638..4b118ca08 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/UpdateTimestampFactory.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/UpdateTimestampFactory.java @@ -9,7 +9,7 @@ import java.util.Map; import javax.persistence.PersistenceException; -import com.avaje.ebeaninternal.api.ClassUtil; +import com.avaje.ebean.config.ClassLoadConfig; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty; /** @@ -21,18 +21,18 @@ public class UpdateTimestampFactory { final Map, GeneratedProperty> map = new HashMap, GeneratedProperty>(); - public UpdateTimestampFactory() { + public UpdateTimestampFactory(ClassLoadConfig classLoadConfig) { map.put(Timestamp.class, new GeneratedUpdateTimestamp()); map.put(java.util.Date.class, new GeneratedUpdateDate()); map.put(Long.class, longTime); map.put(long.class, longTime); - if (ClassUtil.isPresent("java.time.LocalDate", this.getClass())) { + if (classLoadConfig.isJavaTimePresent()) { map.put(LocalDateTime.class, new GeneratedUpdateJavaTime.LocalDT()); map.put(OffsetDateTime.class, new GeneratedUpdateJavaTime.OffsetDT()); map.put(ZonedDateTime.class, new GeneratedUpdateJavaTime.ZonedDT()); } - if (ClassUtil.isPresent("org.joda.time.LocalDateTime", this.getClass())) { + if (classLoadConfig.isJodaTimePresent()) { map.put(org.joda.time.LocalDateTime.class, new GeneratedUpdateJodaTime.LocalDT()); map.put(org.joda.time.DateTime.class, new GeneratedUpdateJodaTime.DateTimeDT()); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/ReadAnnotations.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/ReadAnnotations.java index e9b1b122f..e1bc81db2 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/ReadAnnotations.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/ReadAnnotations.java @@ -1,6 +1,5 @@ package com.avaje.ebeaninternal.server.deploy.parse; -import com.avaje.ebeaninternal.api.ClassUtil; import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager; import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory; @@ -37,8 +36,8 @@ public class ReadAnnotations { this.generatedPropFactory = generatedPropFactory; this.asOfViewSuffix = asOfViewSuffix; this.versionsBetweenSuffix = versionsBetweenSuffix; - this.javaxValidationAnnotations = ClassUtil.isJavaxValidationAnnotationsPresent(); - this.jacksonAnnotations = ClassUtil.isJacksonAnnotationsPresent(); + this.javaxValidationAnnotations = generatedPropFactory.getClassLoadConfig().isJavaxValidationAnnotationsPresent(); + this.jacksonAnnotations = generatedPropFactory.getClassLoadConfig().isJacksonAnnotationsPresent(); } /** diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePool.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePool.java index e49013275..c69983ac4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePool.java +++ b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/DataSourcePool.java @@ -171,10 +171,14 @@ public class DataSourcePool implements DataSource { private final Runnable heartbeatRunnable = new HeartBeatRunnable(); public DataSourcePool(DataSourceAlert notify, String name, DataSourceConfig params) { + this(notify, name, params, null); + } + + public DataSourcePool(DataSourceAlert notify, String name, DataSourceConfig params, DataSourcePoolListener listener) { this.notify = notify; this.name = name; - this.poolListener = createPoolListener(params.getPoolListener()); + this.poolListener = listener; this.autoCommit = params.isAutoCommit(); this.transactionIsolation = params.getIsolationLevel(); @@ -238,20 +242,6 @@ public class DataSourcePool implements DataSource { throw new SQLFeatureNotSupportedException("We do not support java.util.logging"); } - /** - * Create the DataSourcePoolListener if there is one. - */ - private DataSourcePoolListener createPoolListener(String cn) { - if (cn == null) { - return null; - } - try { - return (DataSourcePoolListener) ClassUtil.newInstance(cn, this.getClass()); - } catch (Exception e) { - throw new IllegalArgumentException(e); - } - } - private void initialise() throws SQLException { String transIsolation = TransactionIsolation.getLevelDescription(transactionIsolation); diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java b/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java index 0a81879f1..203f8f0d3 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java @@ -162,13 +162,13 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable { this.typeMap = new ConcurrentHashMap, ScalarType>(); this.nativeMap = new ConcurrentHashMap>(); - this.objectMapperPresent = ClassUtil.isJacksonObjectMapperPresent(); + this.objectMapperPresent = config.getClassLoadConfig().isJacksonObjectMapperPresent(); this.extraTypeFactory = new DefaultTypeFactory(config); initialiseStandard(jsonDateTime, config); initialiseJavaTimeTypes(jsonDateTime, config); - initialiseJodaTypes(jsonDateTime); + initialiseJodaTypes(jsonDateTime, config); initialiseJacksonTypes(config); if (isPostgres(config.getDatabasePlatform())) { @@ -738,7 +738,7 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable { */ protected void initialiseJacksonTypes(ServerConfig config) { - if (ClassUtil.isPresent("com.fasterxml.jackson.databind.ObjectMapper", this.getClass())) { + if (config.getClassLoadConfig().isJacksonObjectMapperPresent()) { logger.trace("Registering JsonNode type support"); @@ -765,7 +765,7 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable { } protected void initialiseJavaTimeTypes(JsonConfig.DateTime mode, ServerConfig config) { - if (ClassUtil.isPresent("java.time.LocalDate", this.getClass())) { + if (config.getClassLoadConfig().isJavaTimePresent()) { logger.debug("Registering java.time data types"); typeMap.put(java.time.LocalDate.class, new ScalarTypeLocalDate()); typeMap.put(java.time.LocalDateTime.class, new ScalarTypeLocalDateTime(mode)); @@ -796,10 +796,10 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable { * Detect if Joda classes are in the classpath and if so register the Joda * data types. */ - protected void initialiseJodaTypes(JsonConfig.DateTime mode) { + protected void initialiseJodaTypes(JsonConfig.DateTime mode, ServerConfig config) { // detect if Joda classes are in the classpath - if (ClassUtil.isPresent("org.joda.time.LocalDateTime", this.getClass())) { + if (config.getClassLoadConfig().isJodaTimePresent()) { // Joda classes are in the classpath so register the types logger.debug("Registering Joda data types"); typeMap.put(LocalDateTime.class, new ScalarTypeJodaLocalDateTime(mode)); diff --git a/src/main/java/com/avaje/ebeaninternal/server/util/ClassPathSearch.java b/src/main/java/com/avaje/ebeaninternal/server/util/ClassPathSearch.java index 2ca1d7ec5..1182d46b9 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/util/ClassPathSearch.java +++ b/src/main/java/com/avaje/ebeaninternal/server/util/ClassPathSearch.java @@ -75,7 +75,7 @@ public class ClassPathSearch implements ClassPathSearchService { if (classPathReaderCN != null) { // use a user defined classPathReader logger.info("Using [" + classPathReaderCN + "] to read the searchable class path"); - classPathReader = (ClassPathReader) ClassUtil.newInstance(classPathReaderCN, this.getClass()); + classPathReader = (ClassPathReader) ClassUtil.newInstance(classPathReaderCN); } Object[] rawClassPaths = classPathReader.readPath(classLoader); diff --git a/src/test/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/InsertTimestampFactoryTest.java b/src/test/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/InsertTimestampFactoryTest.java index 8aca43860..47cf87ced 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/InsertTimestampFactoryTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/InsertTimestampFactoryTest.java @@ -1,5 +1,6 @@ package com.avaje.ebeaninternal.server.deploy.generatedproperty; +import com.avaje.ebean.config.ClassLoadConfig; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty; import org.junit.Test; @@ -11,7 +12,7 @@ import static org.junit.Assert.*; public class InsertTimestampFactoryTest { - InsertTimestampFactory factory = new InsertTimestampFactory(); + InsertTimestampFactory factory = new InsertTimestampFactory(new ClassLoadConfig()); @Test public void test_createdTimestamp_LocalDateTime() { diff --git a/src/test/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/UpdateTimestampFactoryTest.java b/src/test/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/UpdateTimestampFactoryTest.java index f861efe63..956da2a07 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/UpdateTimestampFactoryTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/deploy/generatedproperty/UpdateTimestampFactoryTest.java @@ -1,5 +1,6 @@ package com.avaje.ebeaninternal.server.deploy.generatedproperty; +import com.avaje.ebean.config.ClassLoadConfig; import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty; import org.junit.Test; @@ -12,7 +13,7 @@ import static org.junit.Assert.*; public class UpdateTimestampFactoryTest { - UpdateTimestampFactory factory = new UpdateTimestampFactory(); + UpdateTimestampFactory factory = new UpdateTimestampFactory(new ClassLoadConfig()); @Test public void test_createdTimestamp_LocalDateTime() {