diff --git a/pom.xml b/pom.xml index 83f09aaae..7427e13c7 100644 --- a/pom.xml +++ b/pom.xml @@ -70,11 +70,6 @@ provided - - org.avaje.ebeanorm - avaje-ebeanorm-agent - [3.1.1] - joda-time @@ -141,10 +136,22 @@ org.avaje.ebeanorm avaje-ebeanorm-mavenenhancer - 3.1.1 + 3.2.1 - + main + process-classes + + target/classes + com.avaje.ebean.meta.** + debug=1 + + + enhance + + + + test process-test-classes target/test-classes diff --git a/src/main/java/com/avaje/ebean/EbeanServer.java b/src/main/java/com/avaje/ebean/EbeanServer.java index e31240efe..cd8252962 100644 --- a/src/main/java/com/avaje/ebean/EbeanServer.java +++ b/src/main/java/com/avaje/ebean/EbeanServer.java @@ -1,7 +1,5 @@ package com.avaje.ebean; -import java.io.InputStream; -import java.io.ObjectInputStream; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -138,22 +136,6 @@ public interface EbeanServer { */ public T createEntityBean(Class type); - /** - * Create a ObjectInputStream that can be used to deserialise "Proxy" or - * "SubClassed" entity beans. - *

- * This is NOT required when entity beans are "Enhanced" (via java agent or - * ant task etc). - *

- *

- * The reason this is needed to deserialise "Proxy" beans is because Ebean - * creates the "Proxy/SubClass" classes in a class loader - and generally the - * class loader deserialising the inputStream is not aware of these other - * classes. - *

- */ - public ObjectInputStream createProxyObjectInputStream(InputStream is); - /** * Create a CsvReader for a given beanType. */ diff --git a/src/main/java/com/avaje/ebean/Query.java b/src/main/java/com/avaje/ebean/Query.java index 3aa98653f..6dcfe8478 100644 --- a/src/main/java/com/avaje/ebean/Query.java +++ b/src/main/java/com/avaje/ebean/Query.java @@ -1,7 +1,5 @@ package com.avaje.ebean; -import com.avaje.ebean.config.ServerConfig; - import java.io.Serializable; import java.util.List; import java.util.Map; @@ -959,23 +957,6 @@ public interface Query extends Serializable { */ public Query setDistinct(boolean isDistinct); - /** - * Set this to true and the beans and collections returned will be plain - * classes rather than Ebean generated dynamic subclasses etc. - *

- * This is *ONLY* relevant when you are not using enhancement (and using - * dynamic subclasses instead). - *

- *

- * Alternatively you can globally set the mode using ebean.vanillaMode=true in - * ebean.properties or {@link ServerConfig#setVanillaMode(boolean)}. - *

- * - * @see ServerConfig#setVanillaMode(boolean) - * @see ServerConfig#setVanillaRefMode(boolean) - */ - public Query setVanillaMode(boolean vanillaMode); - /** * Return the first row value. */ diff --git a/src/main/java/com/avaje/ebean/bean/EnhancedTransactional.java b/src/main/java/com/avaje/ebean/bean/EnhancedTransactional.java new file mode 100644 index 000000000..ad46caeff --- /dev/null +++ b/src/main/java/com/avaje/ebean/bean/EnhancedTransactional.java @@ -0,0 +1,8 @@ +package com.avaje.ebean.bean; + +/** + * Marker interface for classes enhanced to support Transactional methods. + */ +public interface EnhancedTransactional { + +} diff --git a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java index 9a62aeeb0..ab9fa87c8 100644 --- a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java +++ b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java @@ -3,7 +3,6 @@ package com.avaje.ebean.bean; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; -import java.io.ObjectStreamException; import java.io.Serializable; import java.math.BigDecimal; import java.net.URL; @@ -536,27 +535,6 @@ public final class EntityBeanIntercept implements Serializable { } } - /** - * This is ONLY used for subclass entity beans. - *

- * This is not used when entity bean classes are enhanced via javaagent or ant - * etc - only when a subclass is generated. - *

- * Returns a Serializable instance that is either the 'byte code generated' - * object or a 'Vanilla' copy of this bean depending on - * SerializeControl.isVanillaBeans(). - */ - public Object writeReplaceIntercept() throws ObjectStreamException { - - if (!SerializeControl.isVanillaBeans()) { - return owner; - } - - // creates a plain vanilla object and - // copies the values from the owner - return owner._ebean_createCopy(); - } - /** * Helper method to check if two objects are equal. */ diff --git a/src/main/java/com/avaje/ebean/bean/SerializeControl.java b/src/main/java/com/avaje/ebean/bean/SerializeControl.java deleted file mode 100644 index e1c829a15..000000000 --- a/src/main/java/com/avaje/ebean/bean/SerializeControl.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.avaje.ebean.bean; - -/** - * This is ONLY used for subclassed entity beans. - *

- * This is NOT USED for entity beans that are enhanced via a javaagent or ant - * task etc. This is only used when the entity beans are created as a subclass - * of the original class. - *

- *

- * Allows the developer to control whether beans and collections are serialized - * to plain 'vanilla' classes or left in byte code generated subclasses. - *

- * Vanilla beans are beans that have plain ordinary classes as opposed to - * specially generated classes that Ebean creates. Ebean creates classes (using - * ASM) to support lazy loading (reference beans) and concurrency checking etc. - *

- *

- * SerializeControl gives you the ability to control whether an object graph is - * serialized to plain 'vanilla' objects or in the special byte code generated - * form. There are pros and cons for both approaches depending on whether you - * want to support "FULL" concurrency checking and lazy loading when the object - * graph is deserialized. - *

- *

- * Note that BeanMap, BeanList and BeanSet are not byte code generated. They are - * ordinary classes. However you may wish to have these serialized to the - * underlying List Set and Map implementations for the benefit that they can be - * deserialised in a JVM without ANY ebean code at all. - *

- */ -public class SerializeControl { - - private static final String BEANS = "com.avaje.ebean.vanillabeans"; - - private static final String COLLECTIONS = "com.avaje.ebean.vanillacollections"; - - private static Boolean getDefault(String key, Boolean dflt) { - String val = System.getProperty(key); - if (val != null) { - return val.equalsIgnoreCase("true"); - } - return dflt; - } - - private static ThreadLocal vanillaBeans = new ThreadLocal() { - protected synchronized Boolean initialValue() { - return getDefault(BEANS, Boolean.TRUE); - } - }; - - private static ThreadLocal vanillaCollections = new ThreadLocal() { - protected synchronized Boolean initialValue() { - return getDefault(COLLECTIONS, Boolean.TRUE); - } - }; - - /** - * Set the JVM wide default for Beans. - */ - public static void setDefaultForBeans(boolean vanillaOn) { - Boolean b = Boolean.valueOf(vanillaOn); - System.setProperty(BEANS, b.toString()); - } - - /** - * Set the JVM wide default for Collections. - */ - public static void setDefaultForCollections(boolean vanillaOn) { - Boolean b = Boolean.valueOf(vanillaOn); - System.setProperty(COLLECTIONS, b.toString()); - } - - /** - * Reset the mode for beans and collections back to the JVM wide default - * setting. - */ - public static void resetToDefault() { - Boolean beans = getDefault(BEANS, Boolean.FALSE); - setVanillaBeans(beans); - - Boolean coll = getDefault(COLLECTIONS, Boolean.FALSE); - setVanillaCollections(coll); - } - - /** - * Set the mode for both Beans and Collections. - */ - public static void setVanilla(boolean vanillaOn) { - if (vanillaOn) { - vanillaBeans.set(Boolean.TRUE); - vanillaCollections.set(Boolean.TRUE); - } else { - vanillaBeans.set(Boolean.FALSE); - vanillaCollections.set(Boolean.FALSE); - } - } - - /** - * Return true if beans are serialized to Vanilla as opposed to byte code - * generated subclasses. - */ - public static boolean isVanillaBeans() { - return (Boolean) vanillaBeans.get(); - } - - /** - * Set whether beans should be serialized to Vanilla as opposed to byte code - * generated subclasses. - */ - public static void setVanillaBeans(boolean vanillaOn) { - vanillaBeans.set(vanillaOn); - } - - /** - * Return true if collections are serialized to be plain Lists Sets or Maps as - * opposed to BeanList, BeanMap or BeanSet. - */ - public static boolean isVanillaCollections() { - return (Boolean) vanillaCollections.get(); - } - - /** - * Set whether collections should be serialized to Vanilla Lists Sets or Maps - * (instead of BeanList, BeanMap or BeanSet). - */ - public static void setVanillaCollections(boolean vanillaOn) { - vanillaCollections.set(vanillaOn); - } -} diff --git a/src/main/java/com/avaje/ebean/common/BeanList.java b/src/main/java/com/avaje/ebean/common/BeanList.java index 7559b4b22..8207eff8e 100644 --- a/src/main/java/com/avaje/ebean/common/BeanList.java +++ b/src/main/java/com/avaje/ebean/common/BeanList.java @@ -1,6 +1,5 @@ package com.avaje.ebean.common; -import java.io.ObjectStreamException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; @@ -11,7 +10,6 @@ import java.util.ListIterator; import com.avaje.ebean.bean.BeanCollectionAdd; import com.avaje.ebean.bean.BeanCollectionLoader; -import com.avaje.ebean.bean.SerializeControl; /** * List capable of lazy loading. @@ -46,20 +44,6 @@ public final class BeanList extends AbstractBeanCollection implements List super(loader, ownerBean, propertyName); } - Object readResolve() throws ObjectStreamException { - if (SerializeControl.isVanillaCollections()) { - return list; - } - return this; - } - - Object writeReplace() throws ObjectStreamException { - if (SerializeControl.isVanillaCollections()) { - return list; - } - return this; - } - @SuppressWarnings("unchecked") public void addBean(Object bean) { list.add((E) bean); diff --git a/src/main/java/com/avaje/ebean/common/BeanMap.java b/src/main/java/com/avaje/ebean/common/BeanMap.java index ea9601195..ff3c3e6f2 100644 --- a/src/main/java/com/avaje/ebean/common/BeanMap.java +++ b/src/main/java/com/avaje/ebean/common/BeanMap.java @@ -1,6 +1,5 @@ package com.avaje.ebean.common; -import java.io.ObjectStreamException; import java.util.Collection; import java.util.Collections; import java.util.Iterator; @@ -9,7 +8,6 @@ import java.util.Map; import java.util.Set; import com.avaje.ebean.bean.BeanCollectionLoader; -import com.avaje.ebean.bean.SerializeControl; /** * Map capable of lazy loading. @@ -39,20 +37,6 @@ public final class BeanMap extends AbstractBeanCollection implements Ma super(ebeanServer, ownerBean, propertyName); } - Object readResolve() throws ObjectStreamException { - if (SerializeControl.isVanillaCollections()) { - return map; - } - return this; - } - - Object writeReplace() throws ObjectStreamException { - if (SerializeControl.isVanillaCollections()) { - return map; - } - return this; - } - public void internalAdd(Object bean) { throw new RuntimeException("Not allowed for map"); } diff --git a/src/main/java/com/avaje/ebean/common/BeanSet.java b/src/main/java/com/avaje/ebean/common/BeanSet.java index 552a5c190..f3a41b4dc 100644 --- a/src/main/java/com/avaje/ebean/common/BeanSet.java +++ b/src/main/java/com/avaje/ebean/common/BeanSet.java @@ -1,6 +1,5 @@ package com.avaje.ebean.common; -import java.io.ObjectStreamException; import java.io.Serializable; import java.util.Collection; import java.util.Iterator; @@ -9,7 +8,6 @@ import java.util.Set; import com.avaje.ebean.bean.BeanCollectionAdd; import com.avaje.ebean.bean.BeanCollectionLoader; -import com.avaje.ebean.bean.SerializeControl; /** * Set capable of lazy loading. @@ -40,20 +38,6 @@ public final class BeanSet extends AbstractBeanCollection implements Set - * This setting is not relevant when using enhancement (only when using - * dynamic subclasses). - *

- */ - public boolean isVanillaMode() { - return vanillaMode; - } - - /** - * Set this to true if by default queries should return 'vanilla' objects - * rather than dynamic subclasses. - *

- * This setting is not relevant when using enhancement (only when using - * dynamic subclasses). - *

- *

- * Alternatively you can set this on a specific query via - * {@link Query#setVanillaMode(boolean)}. - *

- * - * @see #setVanillaRefMode(boolean) - * @see Query#setVanillaMode(boolean) - */ - public void setVanillaMode(boolean vanillaMode) { - this.vanillaMode = vanillaMode; - } - - /** - * Returns true if {@link EbeanServer#getReference(Class, Object)} should - * return vanilla objects or not. - * - * @see #setVanillaMode(boolean) - * @see Query#setVanillaMode(boolean) - */ - public boolean isVanillaRefMode() { - return vanillaRefMode; - } - - /** - * Set this to true if you want - * {@link EbeanServer#getReference(Class, Object)} to return vanilla objects. - */ - public void setVanillaRefMode(boolean vanillaRefMode) { - this.vanillaRefMode = vanillaRefMode; - } - /** * Return the log level used for "subclassing" enhancement. */ @@ -1151,20 +1081,6 @@ public class ServerConfig { this.updateChangesOnly = updateChangesOnly; } - /** - * Set to false to require enhancement to be used. Defaults to true. - */ - public void setAllowSubclassing(boolean allowSubclassing) { - this.allowSubclassing = allowSubclassing; - } - - /** - * Returns whether this config supports subclassed entities. - */ - public boolean isAllowSubclassing() { - return allowSubclassing; - } - /** * Returns the resource directory. */ @@ -1421,9 +1337,6 @@ public class ServerConfig { packages = getSearchJarsPackages(packagesProp); } - allowSubclassing = p.getBoolean("allowSubclassing", true); - vanillaMode = p.getBoolean("vanillaMode", false); - vanillaRefMode = p.getBoolean("vanillaRefMode", false); updateChangesOnly = p.getBoolean("updateChangesOnly", true); boolean batchMode = p.getBoolean("batch.mode", false); diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java b/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java index 6c4ea84c9..818231694 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java +++ b/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java @@ -33,11 +33,6 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL * Return true if UpdateNullProperties defaults to true for stateless updates. */ public boolean isDefaultUpdateNullProperties(); - - /** - * Return true if vanilla beans should be returned by queries by default. - */ - public boolean isVanillaMode(); /** * Return the DatabasePlatform for this server. diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java index 2054aad0c..9c9c3593d 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java @@ -522,11 +522,6 @@ public interface SpiQuery extends Query { */ public boolean isDistinct(); - /** - * Return true if this query should build and return vanilla objects. - */ - public boolean isVanillaMode(boolean serverDefaultVanillaMode); - /** * Set default select clauses where none have been explicitly defined. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBean.java b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBean.java index 0390ffb78..c2f5025c2 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBean.java +++ b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBean.java @@ -76,7 +76,7 @@ public class CachedBeanDataFromBean { sharableBean = bean; } else { // create a readOnly sharable instance by copying the data - sharableBean = desc.createBean(false); + sharableBean = desc.createBean(); BeanProperty[] propertiesId = desc.propertiesId(); for (int i = 0; i < propertiesId.length; i++) { Object v = propertiesId[i].getValue(bean); diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java index 724e1438b..0bd05ca18 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java @@ -34,13 +34,10 @@ public class DefaultBeanLoader { private static final Logger logger = LoggerFactory.getLogger(DefaultBeanLoader.class); - private final DebugLazyLoad debugLazyLoad; - private final DefaultServer server; - protected DefaultBeanLoader(DefaultServer server, DebugLazyLoad debugLazyLoad) { + protected DefaultBeanLoader(DefaultServer server) { this.server = server; - this.debugLazyLoad = debugLazyLoad; } /** @@ -173,17 +170,13 @@ public class DefaultBeanLoader { private void loadManyInternal(Object parentBean, String propertyName, Transaction t, boolean refresh, ObjectGraphNode node, boolean onlyIds) { - boolean vanilla = (parentBean instanceof EntityBean == false); - EntityBeanIntercept ebi = null; PersistenceContext pc = null; BeanCollection beanCollection = null; ExpressionList filterMany = null; - if (!vanilla) { - ebi = ((EntityBean) parentBean)._ebean_getIntercept(); - pc = ebi.getPersistenceContext(); - } + ebi = ((EntityBean) parentBean)._ebean_getIntercept(); + pc = ebi.getPersistenceContext(); BeanDescriptor parentDesc = server.getBeanDescriptor(parentBean.getClass()); BeanPropertyAssocMany many = (BeanPropertyAssocMany) parentDesc.getBeanProperty(propertyName); @@ -201,13 +194,13 @@ public class DefaultBeanLoader { pc.put(parentId, parentBean); } - boolean useManyIdCache = !vanilla && beanCollection != null && parentDesc.cacheIsUseManyId(); + boolean useManyIdCache = beanCollection != null && parentDesc.cacheIsUseManyId(); if (useManyIdCache) { Boolean readOnly = null; if (ebi != null && ebi.isReadOnly()) { readOnly = Boolean.TRUE; } - if (parentDesc.cacheLoadMany(many, beanCollection, parentId, readOnly, false)) { + if (parentDesc.cacheLoadMany(many, beanCollection, parentId, readOnly)) { return; } } @@ -216,7 +209,7 @@ public class DefaultBeanLoader { if (refresh) { // populate a new collection - Object emptyCollection = many.createEmpty(vanilla); + Object emptyCollection = many.createEmpty(false); many.setValue(parentBean, emptyCollection); query.setLoadDescription("+refresh", null); } else { @@ -245,7 +238,6 @@ public class DefaultBeanLoader { query.setMode(Mode.LAZYLOAD_MANY); query.setLazyLoadManyPath(many.getName()); query.setPersistenceContext(pc); - query.setVanillaMode(vanilla); if (ebi != null) { if (ebi.isReadOnly()) { @@ -370,15 +362,9 @@ public class DefaultBeanLoader { private void refreshBeanInternal(Object bean, SpiQuery.Mode mode) { - boolean vanilla = (bean instanceof EntityBean == false); - - EntityBeanIntercept ebi = null; - PersistenceContext pc = null; - - if (!vanilla) { - ebi = ((EntityBean) bean)._ebean_getIntercept(); - pc = ebi.getPersistenceContext(); - } + + EntityBeanIntercept ebi = ((EntityBean) bean)._ebean_getIntercept();; + PersistenceContext pc = ebi.getPersistenceContext(); BeanDescriptor desc = server.getBeanDescriptor(bean.getClass()); Object id = desc.getId(bean); @@ -429,7 +415,6 @@ public class DefaultBeanLoader { if (mode.equals(SpiQuery.Mode.REFRESH_BEAN)) { query.setUseCache(false); } - query.setVanillaMode(vanilla); if (ebi != null && ebi.isReadOnly()) { query.setReadOnly(true); diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java index bc1b9d356..6b9f03126 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java @@ -1,8 +1,5 @@ package com.avaje.ebeaninternal.server.core; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -138,13 +135,6 @@ public final class DefaultServer implements SpiEbeanServer { private final boolean defaultDeleteMissingChildren; private final boolean defaultUpdateNullProperties; - /** - * Set to true if vanilla objects should be returned by default from queries - * (with dynamic subclassing). - */ - private final boolean vanillaMode; - private final boolean vanillaRefMode; - /** * Handles the save, delete, updateSql CallableSql. */ @@ -210,9 +200,6 @@ public final class DefaultServer implements SpiEbeanServer { */ public DefaultServer(InternalConfiguration config, ServerCacheManager cache) { - this.vanillaMode = config.getServerConfig().isVanillaMode(); - this.vanillaRefMode = config.getServerConfig().isVanillaRefMode(); - this.serverCacheManager = cache; this.pstmtBatch = config.getPstmtBatch(); this.databasePlatform = config.getDatabasePlatform(); @@ -245,7 +232,7 @@ public final class DefaultServer implements SpiEbeanServer { this.autoFetchManager = config.createAutoFetchManager(this); this.adminAutofetch = new MAdminAutofetch(autoFetchManager); - this.beanLoader = new DefaultBeanLoader(this, config.getDebugLazyLoad()); + this.beanLoader = new DefaultBeanLoader(this); this.jsonContext = config.createJsonContext(this); loadAndInitializePlugins(config); @@ -290,10 +277,6 @@ public final class DefaultServer implements SpiEbeanServer { return defaultUpdateNullProperties; } - public boolean isVanillaMode() { - return vanillaMode; - } - public int getLazyLoadBatchSize() { return lazyLoadBatchSize; } @@ -410,8 +393,7 @@ public final class DefaultServer implements SpiEbeanServer { if (bean instanceof EntityBean) { return new DefaultBeanState((EntityBean) bean); } - // if using "subclassing" (not enhancement) this will - // return null for 'vanilla' instances (not subclassed) + // Not an entity bean return null; } @@ -563,15 +545,6 @@ public final class DefaultServer implements SpiEbeanServer { return (T) desc.createEntityBean(); } - public ObjectInputStream createProxyObjectInputStream(InputStream is) { - - try { - return new ProxyBeanObjectInputStream(is, this); - } catch (IOException e) { - throw new PersistenceException(e); - } - } - /** * Return a Reference bean. *

@@ -629,7 +602,7 @@ public final class DefaultServer implements SpiEbeanServer { } else { // use the default reference options - ref = desc.createReference(vanillaRefMode, null, id, null); + ref = desc.createReference(null, id, null); } if (ctx != null && (ref instanceof EntityBean)) { @@ -1139,25 +1112,20 @@ public final class DefaultServer implements SpiEbeanServer { return null; } - // boolean readOnly = beanDescriptor.calculateReadOnly(query.isReadOnly()); - boolean vanilla = query.isVanillaMode(vanillaMode); - Object cachedBean = beanDescriptor.cacheGetBean(query.getId(), vanilla, query.isReadOnly()); + Object cachedBean = beanDescriptor.cacheGetBean(query.getId(), query.isReadOnly()); if (cachedBean != null) { if (context == null) { context = new DefaultPersistenceContext(); } context.put(query.getId(), cachedBean); - if (!vanilla) { - DLoadContext loadContext = new DLoadContext(this, beanDescriptor, query.isReadOnly(), false, null, false); - loadContext.setPersistenceContext(context); + DLoadContext loadContext = new DLoadContext(this, beanDescriptor, query.isReadOnly(), false, null, false); + loadContext.setPersistenceContext(context); - EntityBeanIntercept ebi = ((EntityBean) cachedBean)._ebean_getIntercept(); - ebi.setPersistenceContext(context); - loadContext.register(null, ebi); - - } + EntityBeanIntercept ebi = ((EntityBean) cachedBean)._ebean_getIntercept(); + ebi.setPersistenceContext(context); + loadContext.register(null, ebi); } return (T) cachedBean; 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 67604b76a..8490a32cc 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java @@ -29,7 +29,6 @@ import com.avaje.ebeaninternal.server.query.DefaultOrmQueryEngine; import com.avaje.ebeaninternal.server.query.DefaultRelationalQueryEngine; import com.avaje.ebeaninternal.server.resource.ResourceManager; import com.avaje.ebeaninternal.server.resource.ResourceManagerFactory; -import com.avaje.ebeaninternal.server.subclass.SubClassManager; import com.avaje.ebeaninternal.server.text.json.DJsonContext; import com.avaje.ebeaninternal.server.text.json.DefaultJsonValueAdapter; import com.avaje.ebeaninternal.server.transaction.DefaultTransactionScopeManager; @@ -54,8 +53,6 @@ public class InternalConfiguration { private final BootupClasses bootupClasses; - private final SubClassManager subClassManager; - private final DeployInherit deployInherit; private final ResourceManager resourceManager; @@ -105,8 +102,6 @@ public class InternalConfiguration { this.bootupClasses = bootupClasses; this.expressionFactory = new DefaultExpressionFactory(); - this.subClassManager = new SubClassManager(serverConfig); - this.typeManager = new DefaultTypeManager(serverConfig, bootupClasses); this.binder = new Binder(typeManager); @@ -215,10 +210,6 @@ public class InternalConfiguration { return beanDescriptorManager; } - public SubClassManager getSubClassManager() { - return subClassManager; - } - public DeployInherit getDeployInherit() { return deployInherit; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java index 72cb538f2..b50c3610d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java @@ -39,8 +39,6 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe private final SpiQuery query; - private final boolean vanillaMode; - private final BeanFinder finder; private final LoadContext graphContext; @@ -74,7 +72,6 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe this.finder = beanDescriptor.getBeanFinder(); this.queryEngine = queryEngine; this.query = query; - this.vanillaMode = query.isVanillaMode(server.isVanillaMode()); this.readOnly = query.isReadOnly(); this.graphContext = new DLoadContext(ebeanServer, beanDescriptor, readOnly, query); @@ -226,11 +223,7 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe public boolean isFindById() { return query.getType() == Type.BEAN; } - - public boolean isVanillaMode() { - return vanillaMode; - } - + /** * Execute the query as findById. */ @@ -269,8 +262,7 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe */ @SuppressWarnings("unchecked") public List findList() { - BeanCollection bc = queryEngine.findMany(this); - return (List) (vanillaMode ? bc.getActualCollection() : bc); + return (List) queryEngine.findMany(this); } /** @@ -278,8 +270,7 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe */ @SuppressWarnings("unchecked") public Set findSet() { - BeanCollection bc = queryEngine.findMany(this); - return (Set) (vanillaMode ? bc.getActualCollection() : bc); + return (Set)queryEngine.findMany(this); } /** @@ -296,8 +287,7 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe throw new PersistenceException(msg); } } - BeanCollection bc = queryEngine.findMany(this); - return (Map) (vanillaMode ? bc.getActualCollection() : bc); + return (Map) queryEngine.findMany(this); } public SpiQuery.Type getQueryType() { @@ -377,14 +367,6 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe // TODO: Sort out returning BeanCollection from L2 cache return null; - - // BeanCollection bc = beanDescriptor.queryCacheGet(cacheKey); - // if (bc != null && Boolean.FALSE.equals(query.isReadOnly())) { - // // Explicit readOnly=false for query cache - // CopyContext ctx = new CopyContext(vanillaMode, false); - // return new CopyBeanCollection(bc, beanDescriptor, ctx, 5).copy(); - // } - // return bc; } public void putToQueryCache(BeanCollection queryResult) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java index 15d279fe9..50101b5c6 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java @@ -53,11 +53,6 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist protected final boolean isDirty; - /** - * True if this is a vanilla bean. - */ - protected final boolean vanilla; - /** * The bean being persisted. */ @@ -113,8 +108,6 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist this.concurrencyMode = concurrencyMode; this.loadedProps = updateProps; this.changedProps = updateProps; - - this.vanilla = true; this.isDirty = true; this.oldValues = bean; if (bean instanceof EntityBean) { @@ -137,41 +130,24 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist this.controller = beanDescriptor.getPersistController(); this.concurrencyMode = beanDescriptor.getConcurrencyMode(); - - if (bean instanceof EntityBean) { - this.intercept = ((EntityBean) bean)._ebean_getIntercept(); - if (intercept.isReference()) { - // allowed to delete reference objects - // with no concurrency checking - this.concurrencyMode = ConcurrencyMode.NONE; - } - // this is ok to not use isNewOrDirty() as used for updates only - this.isDirty = intercept.isDirty(); - if (!isDirty) { - this.changedProps = intercept.getChangedProps(); - } else { - // merge changed properties on the bean with changed embedded beans - Set beanChangedProps = intercept.getChangedProps(); - Set dirtyEmbedded = beanDescriptor.getDirtyEmbeddedProperties(bean); - this.changedProps = mergeChangedProperties(beanChangedProps, dirtyEmbedded); - } - this.loadedProps = intercept.getLoadedProps(); - this.oldValues = (T) intercept.getOldValues(); - this.vanilla = false; - - } else { - // have to assume the vanilla bean is dirty - this.vanilla = true; - this.isDirty = true; - this.loadedProps = null; - this.changedProps = null; - this.intercept = null; - - // degrade concurrency checking to none for vanilla bean - if (concurrencyMode.equals(ConcurrencyMode.ALL)) { - this.concurrencyMode = ConcurrencyMode.NONE; - } + this.intercept = ((EntityBean) bean)._ebean_getIntercept(); + if (intercept.isReference()) { + // allowed to delete reference objects + // with no concurrency checking + this.concurrencyMode = ConcurrencyMode.NONE; } + // this is ok to not use isNewOrDirty() as used for updates only + this.isDirty = intercept.isDirty(); + if (!isDirty) { + this.changedProps = intercept.getChangedProps(); + } else { + // merge changed properties on the bean with changed embedded beans + Set beanChangedProps = intercept.getChangedProps(); + Set dirtyEmbedded = beanDescriptor.getDirtyEmbeddedProperties(bean); + this.changedProps = mergeChangedProperties(beanChangedProps, dirtyEmbedded); + } + this.loadedProps = intercept.getLoadedProps(); + this.oldValues = (T) intercept.getOldValues(); } /** @@ -632,7 +608,7 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist *

*/ public boolean isDynamicUpdateSql() { - return !vanilla && beanDescriptor.isUpdateChangesOnly() || (loadedProps != null); + return beanDescriptor.isUpdateChangesOnly() || (loadedProps != null); } /** @@ -666,7 +642,9 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist * update. */ public boolean hasChanged(BeanProperty prop) { - + if (changedProps == null) { + return false; + } return changedProps.contains(prop.getName()); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/ProxyBeanObjectInputStream.java b/src/main/java/com/avaje/ebeaninternal/server/core/ProxyBeanObjectInputStream.java deleted file mode 100644 index c497b18b1..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/core/ProxyBeanObjectInputStream.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.avaje.ebeaninternal.server.core; - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectStreamClass; - -import com.avaje.ebean.EbeanServer; -import com.avaje.ebean.bean.SerializeControl; -import com.avaje.ebeaninternal.api.ClassUtil; -import com.avaje.ebeaninternal.api.SpiEbeanServer; -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; -import com.avaje.ebeaninternal.server.subclass.SubClassUtil; - -/** - * Read an ObjectInputStream potentially containing "proxy" / "subclassed" - * entity objects. - *

- * This does not need to be used for "Enhanced" beans... but if you want to - * deserialise "proxy" / "subclassed" beans you need to use this - * ProxyBeanObjectInputStream. The reason is because it is required to resolve - * the class (The class with the $$EntityBean suffix). As this class is in - * another class loader typically as plain ObjectInputStream is unable to resolve - * the class - and hence we need to use this ProxyBeanObjectInputStream. - *

- */ -public class ProxyBeanObjectInputStream extends ObjectInputStream { - - private final SpiEbeanServer ebeanServer; - - /** - * Create with a given InputStream and EbeanServer. - *

- * The EbeanServer should be the one that created the 'proxy' classes that - * were serialised. - *

- */ - public ProxyBeanObjectInputStream(InputStream in, EbeanServer ebeanServer) - throws IOException { - - super(in); - this.ebeanServer = (SpiEbeanServer) ebeanServer; - SerializeControl.setVanilla(false); - } - - /** - * close and reset the serialization mode. - *

- * uses SerializeControl.resetToDefault(). - *

- */ - public void close() throws IOException { - super.close(); - SerializeControl.resetToDefault(); - } - - /** - * Resolve the generated Class potentially using reading the embedded - * MethodInfo. - */ - protected Class resolveGenerated(ObjectStreamClass desc) - throws IOException, ClassNotFoundException { - - String className = desc.getName(); - - String vanillaClassName = SubClassUtil.getSuperClassName(className); - Class vanillaClass = ClassUtil.forName(vanillaClassName, this.getClass()); - - BeanDescriptor d = ebeanServer.getBeanDescriptor(vanillaClass); - if (d == null) { - String msg = "Could not find BeanDescriptor for "+ vanillaClassName; - throw new IOException(msg); - } else { - return d.getFactoryType(); - } - } - - /** - * checks for generated subclasses and handles them appropriately. - */ - protected Class resolveClass(ObjectStreamClass desc) throws IOException, - ClassNotFoundException { - - String className = desc.getName(); - if (SubClassUtil.isSubClass(className)) { - return resolveGenerated(desc); - } - - return super.resolveClass(desc); - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/XmlConfigLoader.java b/src/main/java/com/avaje/ebeaninternal/server/core/XmlConfigLoader.java index 0f846910c..077598eb6 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/XmlConfigLoader.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/XmlConfigLoader.java @@ -87,9 +87,9 @@ public class XmlConfigLoader { if (classPath.isDirectory()) { checkDir(searchFor, xmlList, classPath); - } else if (classPath.getName().endsWith(".jar")) { + } else if (classPath.getName().endsWith(".jar") || classPath.getName().endsWith(".war")) { checkJar(searchFor, xmlList, classPath); - + } else { // this is not expected String msg = "Not a Jar or Directory? " + classPath.getAbsolutePath(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java index 57dc1268e..feb2aea36 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java @@ -936,7 +936,7 @@ public class BeanDescriptor { } } - public boolean cacheLoadMany(BeanPropertyAssocMany many, BeanCollection bc, Object parentId, Boolean readOnly, boolean vanilla) { + public boolean cacheLoadMany(BeanPropertyAssocMany many, BeanCollection bc, Object parentId, Boolean readOnly) { CachedManyIds ids = cacheGetCachedManyIds(parentId, many.getName()); if (ids == null) { @@ -953,7 +953,7 @@ public class BeanDescriptor { bc.checkEmptyLazyLoad(); for (int i = 0; i < idList.size(); i++) { Object id = idList.get(i); - Object refBean = targetDescriptor.createReference(vanilla, readOnly, id, null); + Object refBean = targetDescriptor.createReference(readOnly, id, null); EntityBeanIntercept refEbi = ((EntityBean) refBean)._ebean_getIntercept(); many.add(bc, refBean); @@ -999,22 +999,22 @@ public class BeanDescriptor { * Return a bean from the bean cache. */ @SuppressWarnings("unchecked") - public T cacheGetBean(Object id, boolean vanilla, Boolean readOnly) { + public T cacheGetBean(Object id, Boolean readOnly) { CachedBeanData d = (CachedBeanData) getBeanCache().get(id); if (d == null) { return null; } - if (cacheSharableBeans && !vanilla && !Boolean.FALSE.equals(readOnly)) { + if (cacheSharableBeans && !Boolean.FALSE.equals(readOnly)) { Object bean = d.getSharableBean(); if (bean != null) { return (T) bean; } } - T bean = (T) createBean(vanilla); + T bean = (T) createBean(); convertSetId(id, bean); - if (!vanilla && Boolean.TRUE.equals(readOnly)) { + if (Boolean.TRUE.equals(readOnly)) { ((EntityBean) bean)._ebean_getIntercept().setReadOnly(true); } @@ -1306,20 +1306,10 @@ public class BeanDescriptor { } /** - * Create an EntityBean or "Vanilla" bean depending on the flag. + * Create an EntityBean. */ - public Object createBean(boolean vanillaMode) { - return vanillaMode ? createVanillaBean() : createEntityBean(); - } - - /** - * Create a plain vanilla object. - *

- * Used for EmbeddedId Bean construction. - *

- */ - public Object createVanillaBean() { - return beanReflect.createVanillaBean(); + public Object createBean() { + return createEntityBean(); } /** @@ -1341,9 +1331,9 @@ public class BeanDescriptor { * Create a reference bean based on the id. */ @SuppressWarnings("unchecked") - public T createReference(boolean vanillaMode, Boolean readOnly, Object id, Object parent) { + public T createReference(Boolean readOnly, Object id, Object parent) { - if (cacheSharableBeans && !vanillaMode && !Boolean.FALSE.equals(readOnly)) { + if (cacheSharableBeans && !Boolean.FALSE.equals(readOnly)) { CachedBeanData d = (CachedBeanData) getBeanCache().get(id); if (d != null) { Object shareableBean = d.getSharableBean(); @@ -1353,26 +1343,24 @@ public class BeanDescriptor { } } try { - Object bean = createBean(vanillaMode); + Object bean = createBean(); convertSetId(id, bean); - if (!vanillaMode) { - EntityBean eb = (EntityBean) bean; + EntityBean eb = (EntityBean) bean; - EntityBeanIntercept ebi = eb._ebean_getIntercept(); - ebi.setBeanLoaderByServerName(ebeanServer.getName()); + EntityBeanIntercept ebi = eb._ebean_getIntercept(); + ebi.setBeanLoaderByServerName(ebeanServer.getName()); - if (parent != null) { - // Special case for a OneToOne ... parent - // needs to be added to context prior to query - ebi.setParentBean(parent); - } - - // Note: not creating proxies for many's... - ebi.setReference(); + if (parent != null) { + // Special case for a OneToOne ... parent + // needs to be added to context prior to query + ebi.setParentBean(parent); } + // Note: not creating proxies for many's... + ebi.setReference(); + return (T) bean; } catch (Exception ex) { @@ -2209,17 +2197,6 @@ public class BeanDescriptor { return propertyFirstVersion; } - /** - * Return true if this an Insert (rather than Update) on a non-enhanced bean. - */ - public boolean isVanillaInsert(Object bean) { - if (propertyFirstVersion == null) { - return true; - } - Object versionValue = propertyFirstVersion.getValue(bean); - return DmlUtil.isNullOrZero(versionValue); - } - /** * Return true if this is an Update (rather than insert) given that the bean * is involved in a stateless update. diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java index 5258de71b..702c65a08 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java @@ -14,6 +14,9 @@ import java.util.Set; import javax.persistence.PersistenceException; import javax.sql.DataSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.avaje.ebean.BackgroundExecutor; import com.avaje.ebean.RawSql; import com.avaje.ebean.RawSqlBuilder; @@ -60,11 +63,7 @@ import com.avaje.ebeaninternal.server.reflect.BeanReflectFactory; import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter; import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter; import com.avaje.ebeaninternal.server.reflect.EnhanceBeanReflectFactory; -import com.avaje.ebeaninternal.server.subclass.SubClassManager; -import com.avaje.ebeaninternal.server.subclass.SubClassUtil; import com.avaje.ebeaninternal.server.type.TypeManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Creates BeanDescriptors. @@ -98,8 +97,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap { private final BeanQueryAdapterManager beanQueryAdapterManager; - private final SubClassManager subClassManager; - private final NamingConvention namingConvention; private final DeployCreateProperties createProperties; @@ -153,8 +150,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap { private final XmlConfig xmlConfig; - private final boolean allowSubclassing; - /** * Create for a given database dbConfig. */ @@ -172,7 +167,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap { this.bootupClasses = config.getBootupClasses(); this.createProperties = config.getDeployCreateProperties(); - this.subClassManager = config.getSubClassManager(); this.typeManager = config.getTypeManager(); this.namingConvention = config.getServerConfig().getNamingConvention(); this.dbIdentity = config.getDatabasePlatform().getDbIdentity(); @@ -192,7 +186,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap { this.reflectFactory = createReflectionFactory(); this.transientProperties = new TransientProperties(); - this.allowSubclassing = config.getServerConfig().isAllowSubclassing(); } public BeanDescriptor getBeanDescriptorById(String descriptorId) { @@ -201,17 +194,11 @@ public class BeanDescriptorManager implements BeanDescriptorMap { @SuppressWarnings("unchecked") public BeanDescriptor getBeanDescriptor(Class entityType) { - - // remove $$EntityBean stuff - String className = SubClassUtil.getSuperClassName(entityType.getName()); - return (BeanDescriptor) descMap.get(className); + return (BeanDescriptor) descMap.get(entityType.getName()); } @SuppressWarnings("unchecked") public BeanDescriptor getBeanDescriptor(String entityClassName) { - - // remove $$EntityBean stuff - entityClassName = SubClassUtil.getSuperClassName(entityClassName); return (BeanDescriptor) descMap.get(entityClassName); } @@ -440,8 +427,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap { } public BeanManager getBeanManager(String beanClassName) { - - beanClassName = SubClassUtil.getSuperClassName(beanClassName); return beanManagerMap.get(beanClassName); } @@ -1462,13 +1447,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap { desc.setFactoryType(beanClass); } else { - if (!allowSubclassing) { - throw new PersistenceException("This configuration does not allow entity subclassing [" + beanClass + "]"); - } - subclassClassCount++; - Class subClass = subClassManager.resolve(beanClass.getName()); - desc.setFactoryType(subClass); - subclassedEntities.add(desc.getName()); + throw new PersistenceException("Entity type "+beanClass+" is not an enhanced entity bean. Subclassing is not longer supported in Ebean"); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java index 68957aa9a..3352f7dd2 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java @@ -382,13 +382,12 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc { if (embedded){ throw new RuntimeException(); } else { - boolean vanillaMode = false; - T ref = targetDescriptor.createReference(vanillaMode, Boolean.FALSE, cacheData, null); + T ref = targetDescriptor.createReference(Boolean.FALSE, cacheData, null); setValue(bean, ref); if (oldValues != null){ setValue(oldValues, ref); } - if (readOnly && !vanillaMode){ + if (readOnly){ ((EntityBean)ref)._ebean_intercept().setReadOnly(true); } } @@ -438,11 +437,11 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc { /** - * Create a vanilla bean of the target type to be used as an embeddedId + * Create a bean of the target type to be used as an embeddedId * value. */ public Object createEmbeddedId() { - return getTargetDescriptor().createVanillaBean(); + return getTargetDescriptor().createBean(); } /** @@ -736,16 +735,14 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc { // parent always null for this case (but here to document) Object parent = null; - boolean vanillaMode = ctx.isVanillaMode(); - //ReferenceOptions options = ctx.getReferenceOptionsFor(beanProp); Boolean readOnly = ctx.isReadOnly(); Object ref; if (targetInheritInfo != null) { // for inheritance hierarchy create the correct type for this row... - ref = rowDescriptor.createReference(vanillaMode, readOnly, id, parent); + ref = rowDescriptor.createReference(readOnly, id, parent); } else { - ref = targetDescriptor.createReference(vanillaMode, readOnly, id, parent); + ref = targetDescriptor.createReference(readOnly, id, parent); } Object existingBean = ctx.getPersistenceContext().putIfAbsent(id, ref); @@ -755,7 +752,7 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc { // loaded a matching bean so we will use that instead. ref = existingBean; - } else if (!vanillaMode){ + } else { EntityBeanIntercept ebi = ((EntityBean) ref)._ebean_getIntercept(); if (Boolean.TRUE.equals(ctx.isReadOnly())){ ebi.setReadOnly(true); @@ -831,18 +828,15 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc { if (existing != null) { return existing; } - boolean vanillaMode = ctx.isVanillaMode(); Object parent = null; - Object ref = targetDescriptor.createReference(vanillaMode, ctx.isReadOnly(), id, parent); + Object ref = targetDescriptor.createReference(ctx.isReadOnly(), id, parent); - if (!vanillaMode){ - EntityBeanIntercept ebi = ((EntityBean) ref)._ebean_getIntercept(); - if (Boolean.TRUE.equals(ctx.isReadOnly())) { - ebi.setReadOnly(true); - } - persistCtx.put(id, ref); - ctx.register(name, ebi); + EntityBeanIntercept ebi = ((EntityBean) ref)._ebean_getIntercept(); + if (Boolean.TRUE.equals(ctx.isReadOnly())) { + ebi.setReadOnly(true); } + persistCtx.put(id, ref); + ctx.register(name, ebi); return ref; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/DbReadContext.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/DbReadContext.java index 965e168a6..f7b79ef6d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/DbReadContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/DbReadContext.java @@ -13,35 +13,25 @@ import com.avaje.ebeaninternal.server.type.DataReader; */ public interface DbReadContext { - /** - * Return the state of the object graph. - */ - public Boolean isReadOnly(); + /** + * Return the state of the object graph. + */ + public Boolean isReadOnly(); + + /** + * Propagate the state to the bean. + */ + public void propagateState(Object e); - /** - * Propagate the state to the bean. - */ - public void propagateState(Object e); - - /** - * Return the DataReader. - */ - public DataReader getDataReader(); - - /** - * Return true if vanilla objects should be returned. - */ - public boolean isVanillaMode(); - + /** + * Return the DataReader. + */ + public DataReader getDataReader(); + /** * Return true if the query is using supplied SQL rather than generated SQL. */ public boolean isRawSql(); - -// /** -// * Return the reference options for a given bean property. -// */ -// public ReferenceOptions getReferenceOptionsFor(BeanPropertyAssocOne beanProperty); /** * Set the JoinNode - used by proxy/reference beans for profiling. diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java index eaf2c853a..30c259d98 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/InheritInfo.java @@ -10,7 +10,6 @@ import com.avaje.ebeaninternal.server.core.InternString; import com.avaje.ebeaninternal.server.deploy.id.IdBinder; import com.avaje.ebeaninternal.server.deploy.parse.DeployInheritInfo; import com.avaje.ebeaninternal.server.query.SqlTreeProperties; -import com.avaje.ebeaninternal.server.subclass.SubClassUtil; /** * Represents a node in the Inheritance tree. Holds information regarding Super @@ -224,8 +223,8 @@ public class InheritInfo { /** * Create an EntityBean for this type. */ - public Object createBean(boolean vanillaMode) { - return descriptor.createBean(vanillaMode); + public Object createBean() { + return descriptor.createBean(); } /** @@ -284,8 +283,7 @@ public class InheritInfo { * Return the InheritInfo for the given bean type. */ private InheritInfo getTypeByClass(Class beanType) { - String clsName = SubClassUtil.getSuperClassName(beanType.getName()); - return typeMap.get(clsName); + return typeMap.get(beanType.getName()); } private void registerWithRoot(InheritInfo info) { @@ -293,8 +291,7 @@ public class InheritInfo { String stringDiscValue = info.getDiscriminatorStringValue(); discMap.put(stringDiscValue, info); } - String clsName = SubClassUtil.getSuperClassName(info.getType().getName()); - typeMap.put(clsName, info); + typeMap.put(info.getType().getName(), info); } /** diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java index 22dbdec5a..59a7446b4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java @@ -238,7 +238,7 @@ public final class IdBinderEmbedded implements IdBinder { String msg = "Failed to split ["+idTermValue+"] using | for id."; throw new PersistenceException(msg); } - Object embId = idDesc.createVanillaBean(); + Object embId = idDesc.createBean(); for (int i = 0; i < props.length; i++) { Object v = props[i].getScalarType().parse(split[i]); props[i].setValue(embId, v); @@ -299,7 +299,7 @@ public final class IdBinderEmbedded implements IdBinder { public Object readData(DataInput dataInput) throws IOException { - Object embId = idDesc.createVanillaBean(); + Object embId = idDesc.createBean(); boolean notNull = true; for (int i = 0; i < props.length; i++) { @@ -332,7 +332,7 @@ public final class IdBinderEmbedded implements IdBinder { public Object read(DbReadContext ctx) throws SQLException { - Object embId = idDesc.createVanillaBean(); + Object embId = idDesc.createBean(); boolean notNull = true; for (int i = 0; i < props.length; i++) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnection.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnection.java index 6782a80fd..e0074771e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnection.java +++ b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnection.java @@ -253,8 +253,6 @@ public class PooledConnection extends ConnectionDelegator */ public void closeConnectionFully(boolean logErrors) { - //pool.removeConnection(this); - String msg = "Closing Connection[" + getName() + "]" + " psReuse[" + pstmtHitCounter + "] psCreate[" + pstmtMissCounter + "] psSize[" + pstmtCache.size() + "]"; @@ -262,14 +260,12 @@ public class PooledConnection extends ConnectionDelegator try { if (connection.isClosed()) { - msg = "Closing Connection[" + getName() + "] that is already closed?"; - logger.error(msg); + logger.warn("Closing Connection[" + getName() + "] that is already closed?"); return; } } catch (SQLException ex) { if (logErrors) { - msg = "Error when fully closing connection [" + getName() + "]"; - logger.error(msg, ex); + logger.error("Error when fully closing connection [" + getName() + "]", ex); } } @@ -288,11 +284,9 @@ public class PooledConnection extends ConnectionDelegator try { connection.close(); - } catch (SQLException ex) { if (logErrors) { - msg = "Error when fully closing connection [" + getName() + "]"; - logger.error(msg, ex); + logger.error("Error when fully closing connection [" + getName() + "]", ex); } } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionQueue.java b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionQueue.java index 4ea85069b..8ef09780a 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionQueue.java +++ b/src/main/java/com/avaje/ebeaninternal/server/lib/sql/PooledConnectionQueue.java @@ -338,8 +338,7 @@ public class PooledConnectionQueue { closeFreeConnections(true); if (!busyList.isEmpty()) { - String msg = "A potential connection leak was detected. Busy connections: "+ busyList.size(); - logger.warn(msg); + logger.warn("A potential connection leak was detected. Busy connections: "+ busyList.size()); dumpBusyConnectionInformation(); closeBusyConnections(0); diff --git a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadManyContext.java b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadManyContext.java index 677e8c6ea..1d20d7e4b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadManyContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadManyContext.java @@ -126,7 +126,7 @@ public class DLoadManyContext implements LoadManyContext, BeanCollectionLoader { Object ownerBean = bc.getOwnerBean(); BeanDescriptor parentDesc = desc.getBeanDescriptor(ownerBean.getClass()); Object parentId = parentDesc.getId(ownerBean); - if (parentDesc.cacheLoadMany(property, bc, parentId, parent.isReadOnly(), false)) { + if (parentDesc.cacheLoadMany(property, bc, parentId, parent.isReadOnly())) { // we loaded the bean from cache weakList.removeEntry(position); return; diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java index 3a560f435..36703a88e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java @@ -70,8 +70,8 @@ public final class DefaultPersister implements Persister { private final BeanDescriptorManager beanDescriptorManager; - private final boolean defaultUpdateNullProperties; - private final boolean defaultDeleteMissingChildren; +// private final boolean defaultUpdateNullProperties; +// private final boolean defaultDeleteMissingChildren; public DefaultPersister(SpiEbeanServer server, Binder binder, BeanDescriptorManager descMgr, PstmtBatch pstmtBatch) { @@ -79,8 +79,8 @@ public final class DefaultPersister implements Persister { this.beanDescriptorManager = descMgr; this.persistExecute = new DefaultPersistExecute(binder, pstmtBatch); - this.defaultUpdateNullProperties = server.isDefaultUpdateNullProperties(); - this.defaultDeleteMissingChildren = server.isDefaultDeleteMissingChildren(); +// this.defaultUpdateNullProperties = server.isDefaultUpdateNullProperties(); +// this.defaultDeleteMissingChildren = server.isDefaultDeleteMissingChildren(); } /** @@ -271,8 +271,7 @@ public final class DefaultPersister implements Persister { } if (bean instanceof EntityBean == false) { - saveVanillaRecurse(bean, t, parentBean); - return; + throw new IllegalArgumentException("This bean is of type ["+bean.getClass()+"] is not enhanced?"); } PersistRequestBean req = createRequest(bean, t, parentBean); @@ -313,42 +312,6 @@ public final class DefaultPersister implements Persister { } } - /** - * Determine if this is an Insert or update for the 'vanilla' bean. - */ - private void saveVanillaRecurse(Object bean, Transaction t, Object parentBean) { - - BeanManager mgr = getBeanManager(bean); - if (mgr == null) { - throw new RuntimeException("No Mgr found for " + bean + " " + bean.getClass()); - } - // use the version property to determine insert or update - if (mgr.getBeanDescriptor().isVanillaInsert(bean)) { - saveVanillaInsert(bean, t, parentBean, mgr); - - } else { - // update non-null properties (no partial object knowledge with vanilla bean) - forceUpdateStateless(bean, t, parentBean, mgr, null, defaultDeleteMissingChildren, defaultUpdateNullProperties); - } - } - - /** - * Perform insert on non-enhanced bean (effectively same as enhanced bean). - */ - private void saveVanillaInsert(Object bean, Transaction t, Object parentBean, BeanManager mgr) { - - PersistRequestBean req = createRequest(bean, t, parentBean, mgr); - try { - req.initTransIfRequired(); - insert(req); - req.commitTransIfRequired(); - - } catch (RuntimeException ex) { - req.rollbackTransIfRequired(); - throw ex; - } - } - /** * Insert the bean. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/dml/MetaFactory.java b/src/main/java/com/avaje/ebeaninternal/server/persist/dml/MetaFactory.java index d57559d4d..dd8edeafe 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/dml/MetaFactory.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/dml/MetaFactory.java @@ -72,8 +72,8 @@ public class MetaFactory { embeddedFact.create(allList, desc, DmlMode.WHERE, false); assocOneFact.create(allList, desc, DmlMode.WHERE); - Bindable setBindable = new BindableList(setList); - Bindable allBindable = new BindableList(allList); + BindableList setBindable = new BindableList(setList); + BindableList allBindable = new BindableList(allList); return new UpdateMeta(emptyStringAsNull, desc, setBindable, id, ver, allBindable); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdateMeta.java b/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdateMeta.java index 56782351a..ddb9d5692 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdateMeta.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdateMeta.java @@ -25,7 +25,7 @@ public final class UpdateMeta { private final String sqlNone; - private final Bindable set; + private final BindableList set; private final BindableId id; private final Bindable version; private final Bindable all; @@ -37,7 +37,7 @@ public final class UpdateMeta { private final boolean emptyStringAsNull; - public UpdateMeta(boolean emptyStringAsNull, BeanDescriptor desc, Bindable set, BindableId id, Bindable version, Bindable all) { + public UpdateMeta(boolean emptyStringAsNull, BeanDescriptor desc, BindableList set, BindableId id, Bindable version, Bindable all) { this.emptyStringAsNull = emptyStringAsNull; this.tableName = desc.getBaseTable(); this.set = set; @@ -154,7 +154,12 @@ public final class UpdateMeta { // build a bindableList that only contains the changed properties List list = new ArrayList(); - set.addChanged(persistRequest, list); + if (updatedProps == null) { + // update all the properties + set.addAll(list); + } else { + set.addChanged(persistRequest, list); + } BindableList bindableList = new BindableList(list); // build the SQL for this update statement diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableList.java b/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableList.java index f12c9ee89..924094f6d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableList.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/dmlbind/BindableList.java @@ -17,6 +17,12 @@ public class BindableList implements Bindable { items = list.toArray(new Bindable[list.size()]); } + public void addAll(List list) { + for (int i = 0; i < items.length; i++) { + list.add(items[i]); + } + } + public void addChanged(PersistRequestBean request, List list) { for (int i = 0; i < items.length; i++) { items[i].addChanged(request, list); diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java index de9e1b1d7..20f036e07 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java @@ -317,13 +317,6 @@ public class CQuery implements DbReadContext, CancelableQuery { return queryMode; } - /** - * Return true if we want to return vanilla (not enhanced) objects. - */ - public boolean isVanillaMode() { - return request.isVanillaMode(); - } - public CQueryPredicates getPredicates() { return predicates; } @@ -586,11 +579,11 @@ public class CQuery implements DbReadContext, CancelableQuery { currentDetailCollection = manyPropertyEl.elGetValue(loadedBean); } else { // create a new collection to populate and assign to the bean - currentDetailCollection = manyProperty.createEmpty(request.isVanillaMode()); + currentDetailCollection = manyProperty.createEmpty(false); manyPropertyEl.elSetValue(loadedBean, currentDetailCollection, false, false); } - if (filterMany != null && !request.isVanillaMode()) { + if (filterMany != null) { // remember the for use with a refresh ((BeanCollection) currentDetailCollection).setFilterMany(filterMany); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchIds.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchIds.java index b4fcccea3..3fc8782a4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchIds.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchIds.java @@ -263,10 +263,6 @@ public class CQueryFetchIds { return dataReader; } - public boolean isVanillaMode() { - return false; - } - public Boolean isReadOnly() { return Boolean.FALSE; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java b/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java index b356b676c..a73727211 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java @@ -196,7 +196,7 @@ public class SqlTreeNodeBean implements SqlTreeNode { localType = null; localDesc = desc; } else { - localBean = localInfo.createBean(ctx.isVanillaMode()); + localBean = localInfo.createBean(); localType = localInfo.getType(); localIdBinder = localInfo.getIdBinder(); localDesc = localInfo.getBeanDescriptor(); @@ -205,7 +205,7 @@ public class SqlTreeNodeBean implements SqlTreeNode { } else { localType = null; localDesc = desc; - localBean = desc.createBean(ctx.isVanillaMode()); + localBean = desc.createBean(); localIdBinder = idBinder; } @@ -295,11 +295,7 @@ public class SqlTreeNodeBean implements SqlTreeNode { } else if (localBean != null) { ctx.setCurrentPrefix(prefix, pathMap); - if (!ctx.isVanillaMode()) { - // only create lazy loading collection proxies - // when not in vanilla mode - createListProxies(localDesc, ctx, localBean); - } + createListProxies(localDesc, ctx, localBean); localDesc.postLoad(localBean, includedProps); diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java index 22ab55428..5da53707b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java @@ -128,11 +128,6 @@ public class DefaultOrmQuery implements SpiQuery { private String lazyLoadProperty; private String lazyLoadManyPath; - - /** - * Set to true when we want to return vanilla (not enhanced) objects. - */ - private Boolean vanillaMode; /** * Set to true if you want a DISTINCT query. @@ -447,7 +442,6 @@ public class DefaultOrmQuery implements SpiQuery { copy.timeout = timeout; copy.mapKey = mapKey; copy.id = id; - copy.vanillaMode = vanillaMode; copy.loadBeanCache = loadBeanCache; copy.useBeanCache = useBeanCache; copy.useQueryCache = useQueryCache; @@ -776,20 +770,7 @@ public class DefaultOrmQuery implements SpiQuery { return maxRows > 0 || firstRow > 0; } - - public boolean isVanillaMode(boolean defaultVanillaMode) { - if (vanillaMode != null) { - return vanillaMode.booleanValue(); - } - return defaultVanillaMode; - } - - public DefaultOrmQuery setVanillaMode(boolean vanillaMode) { - this.vanillaMode = vanillaMode; - return this; - } - - public Boolean isReadOnly() { + public Boolean isReadOnly() { return readOnly; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/subclass/GenSuffix.java b/src/main/java/com/avaje/ebeaninternal/server/subclass/GenSuffix.java deleted file mode 100644 index 12655ac87..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/subclass/GenSuffix.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.avaje.ebeaninternal.server.subclass; - -/** - * The suffix used build a generated EntityBean class. - *

- * Note that the server name can be appended after - *

- */ -public interface GenSuffix { - - /** - * The suffix added to the super class name. - */ - public static final String SUFFIX = "$$EntityBean"; - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/subclass/GetterSetterMethods.java b/src/main/java/com/avaje/ebeaninternal/server/subclass/GetterSetterMethods.java deleted file mode 100644 index 13c392e84..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/subclass/GetterSetterMethods.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.avaje.ebeaninternal.server.subclass; - -import java.util.List; - -import com.avaje.ebean.enhance.agent.ClassMeta; -import com.avaje.ebean.enhance.agent.EnhanceConstants; -import com.avaje.ebean.enhance.agent.FieldMeta; -import com.avaje.ebean.enhance.asm.ClassVisitor; -import com.avaje.ebean.enhance.asm.Opcodes; - -public class GetterSetterMethods implements Opcodes, EnhanceConstants { - - /** - * Add getters and setters to for interception. - *

- * Note that we don't intercept Id properties and we don't intercept setters - * on 'OneToMany' properties etc. - *

- */ - public static void add(ClassVisitor cv, ClassMeta classMeta) { - - List localFields = classMeta.getLocalFields(); - for (int x = 0; x < localFields.size(); x++) { - FieldMeta fieldMeta = localFields.get(x); - fieldMeta.addPublicGetSetMethods(cv, classMeta, true); - } - - List inheritedFields = classMeta.getInheritedFields(); - for (int i = 0; i < inheritedFields.size(); i++) { - FieldMeta fieldMeta = inheritedFields.get(i); - // for persistent inherited fields add a - // getter and setter to enable interception - fieldMeta.addPublicGetSetMethods(cv, classMeta, false); - } - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/subclass/MethodWriteReplace.java b/src/main/java/com/avaje/ebeaninternal/server/subclass/MethodWriteReplace.java deleted file mode 100644 index 0eb9227fb..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/subclass/MethodWriteReplace.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.avaje.ebeaninternal.server.subclass; - -import com.avaje.ebean.enhance.agent.ClassMeta; -import com.avaje.ebean.enhance.agent.EnhanceConstants; -import com.avaje.ebean.enhance.asm.ClassVisitor; -import com.avaje.ebean.enhance.asm.Label; -import com.avaje.ebean.enhance.asm.MethodVisitor; -import com.avaje.ebean.enhance.asm.Opcodes; - -/** - * Add a writeReplace method to support optional serialization to vanilla beans. - * - *

- * private Object writeReplace() throws ObjectStreamException {
- * 	return ebeanIntercept.writeReplaceIntercept();
- * }
- * 
- */ -public class MethodWriteReplace implements Opcodes, EnhanceConstants { - - /** - * Add a writeReplace() method. - */ - public static void add(ClassVisitor cv, ClassMeta classMeta) { - - MethodVisitor mv = cv.visitMethod(ACC_PRIVATE, "writeReplace", "()Ljava/lang/Object;", - null, new String[] { "java/io/ObjectStreamException" }); - - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitLineNumber(1, l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, classMeta.getClassName(), INTERCEPT_FIELD, L_INTERCEPT); - mv.visitMethodInsn(INVOKEVIRTUAL, C_INTERCEPT, "writeReplaceIntercept","()Ljava/lang/Object;"); - - mv.visitInsn(ARETURN); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitLocalVariable("this", "L"+classMeta.getClassName()+";", null, l0, l1, 0); - mv.visitMaxs(0, 0); - mv.visitEnd(); - - } -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassClassAdpater.java b/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassClassAdpater.java deleted file mode 100644 index 000c17437..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassClassAdpater.java +++ /dev/null @@ -1,265 +0,0 @@ -package com.avaje.ebeaninternal.server.subclass; - -import com.avaje.ebean.enhance.agent.AlreadyEnhancedException; -import com.avaje.ebean.enhance.agent.ClassMeta; -import com.avaje.ebean.enhance.agent.EnhanceConstants; -import com.avaje.ebean.enhance.agent.EnhanceContext; -import com.avaje.ebean.enhance.agent.IndexFieldWeaver; -import com.avaje.ebean.enhance.agent.InterceptField; -import com.avaje.ebean.enhance.agent.MarkerField; -import com.avaje.ebean.enhance.agent.MethodEquals; -import com.avaje.ebean.enhance.agent.MethodIsEmbeddedNewOrDirty; -import com.avaje.ebean.enhance.agent.MethodNewInstance; -import com.avaje.ebean.enhance.agent.MethodPropertyChangeListener; -import com.avaje.ebean.enhance.agent.MethodSetEmbeddedLoaded; -import com.avaje.ebean.enhance.agent.NoEnhancementRequiredException; -import com.avaje.ebean.enhance.agent.VisitMethodParams; -import com.avaje.ebean.enhance.asm.AnnotationVisitor; -import com.avaje.ebean.enhance.asm.ClassAdapter; -import com.avaje.ebean.enhance.asm.ClassVisitor; -import com.avaje.ebean.enhance.asm.FieldVisitor; -import com.avaje.ebean.enhance.asm.MethodVisitor; -import com.avaje.ebean.enhance.asm.Opcodes; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SubClassClassAdpater extends ClassAdapter implements EnhanceConstants { - - private static final Logger logger = LoggerFactory.getLogger(SubClassClassAdpater.class); - - final EnhanceContext enhanceContext; - - final ClassLoader classLoader; - - final ClassMeta classMeta; - - final String subClassSuffix; - - boolean firstMethod = true; - - public SubClassClassAdpater(String subClassSuffix, ClassVisitor cv, ClassLoader classLoader, EnhanceContext context) { - super(cv); - this.subClassSuffix = subClassSuffix; - this.classLoader = classLoader; - this.enhanceContext = context; - this.classMeta = context.createClassMeta(); - } - - public boolean isLog(int level){ - return classMeta.isLog(level); - } - - public void log(String msg){ - classMeta.log(msg); - } - - /** - * Create the class definition replacing the className and super class. - */ - public void visit(int version, int access, String name, String signature, String superName, - String[] interfaces) { - - // Note: interfaces can be an empty array but not null - int n = 1 + interfaces.length; - String[] c = new String[n]; - for (int i = 0; i < interfaces.length; i++) { - c[i] = interfaces[i]; - if (c[i].equals(C_ENTITYBEAN)) { - throw new AlreadyEnhancedException(name); - } - if (c[i].equals(C_SCALAOBJECT)) { - classMeta.setScalaInterface(true); - } - if (c[i].equals(C_GROOVYOBJECT)) { - classMeta.setGroovyInterface(true); - } - } - - // Add the EntityBean interface - c[c.length - 1] = C_ENTITYBEAN; - - if (!superName.equals("java/lang/Object")){ - - ClassMeta superMeta = enhanceContext.getSuperMeta(superName, classLoader); - if (superMeta != null) { - classMeta.setSuperMeta(superMeta); - if (classMeta.isLog(2)){ - classMeta.log("entity inheritance "+superMeta.getDescription()); - } - } - } - - // adjust the superName and name as we - // are actually creating a subclass of - // the class being visited - superName = name; - name = name+subClassSuffix; - - classMeta.setClassName(name, superName); - - super.visit(version, access, name, signature, superName, c); - } - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - classMeta.addClassAnnotation(desc); - return super.visitAnnotation(desc, visible); - } - - /** - * The ebeanIntercept field is added once but thats all. Note the other - * fields are defined in the superclass. - */ - public FieldVisitor visitField(int access, String name, String desc, String signature, - Object value) { - - if ((access & Opcodes.ACC_STATIC) != 0) { - // no interception of static fields - if (isLog(2)){ - log("Skip intercepting static field "+name); - } - return null; - } - - if ((access & Opcodes.ACC_TRANSIENT) != 0) { - // no interception of transient fields - if (classMeta.isLog(2)){ - classMeta.log("Skip intercepting transient field "+name); - } - return null; - } - - // read the field and associated annotations... - if (classMeta.isLog(5)){ - classMeta.log(" ... reading field:"+name+" desc:"+desc); - } - - return classMeta.createLocalFieldVisitor(name, desc); - } - - /** - * Replace the method code with calls to super. Add the intercept code as - * required. - */ - public MethodVisitor visitMethod(int access, String name, String desc, String signature, - String[] exceptions) { - - if (firstMethod){ - if (!classMeta.isEntityEnhancementRequired()) { - // skip the rest of the visiting etc - throw new NoEnhancementRequiredException(); - } - - // always add the marker field on every enhanced class - String marker = MarkerField.addField(cv, classMeta.getClassName()); - if (isLog(4)){ - log("... add marker field \""+marker+"\""); - log("... add intercept and identity fields"); - } - - // always add these fields for subclass generation - InterceptField.addField(cv, enhanceContext.isTransientInternalFields()); - MethodEquals.addIdentityField(cv); - firstMethod = false; - } - - - VisitMethodParams params = new VisitMethodParams(cv, access, name, desc, signature, exceptions); - - if (isDefaultConstructor(access, name, desc, signature, exceptions)){ - SubClassConstructor.add(params, classMeta); - return null; - } - - if (isSpecialMethod(access, name, desc)) { - return null; - } - - // register the method so that we can check - // if it exists when GetterSetterMethods.add() - // is called. May not exist on read only type - // entity beans such as the internal meta beans. - classMeta.addExistingSuperMethod(name, desc); - - return null; - } - - /** - * Add methods to get and set the entityBeanIntercept. Also add the - * writeReplace method to control serialisation. - */ - public void visitEnd() { - - if (!classMeta.isEntityEnhancementRequired()){ - throw new NoEnhancementRequiredException(); - } - - if (!classMeta.hasDefaultConstructor()){ - if (isLog(2)){ - log("... adding default constructor"); - } - SubClassConstructor.addDefault(cv, classMeta); - } - - MarkerField.addGetMarker(cv, classMeta.getClassName()); - - // Add the _ebean_getIntercept() _ebean_setIntercept() methods - InterceptField.addGetterSetter(cv, classMeta.getClassName()); - - // Add add/removePropertyChangeListener methods - MethodPropertyChangeListener.addMethod(cv, classMeta); - - // Add getter and setter methods for both local - // and inherited properties - GetterSetterMethods.add(cv, classMeta); - - // Add extra methods such as getField(index) etc - IndexFieldWeaver.addMethods(cv, classMeta); - - MethodSetEmbeddedLoaded.addMethod(cv, classMeta); - MethodIsEmbeddedNewOrDirty.addMethod(cv, classMeta); - MethodNewInstance.addMethod(cv, classMeta); - - // add a writeReplace method to control serialisation - MethodWriteReplace.add(cv, classMeta); - - // register with the context - enhanceContext.addClassMeta(classMeta); - - super.visitEnd(); - } - - /** - * Return true if this is the default (no arg) constructor. - */ - private boolean isDefaultConstructor(int access, String name, String desc, String signature, - String[] exceptions){ - - if (name.equals("") && desc.equals("()V")) { - classMeta.setHasDefaultConstructor(true); - return true; - } - - return false; - } - - /** - * Take note of hashcode and equals. - */ - private boolean isSpecialMethod(int access, String name, String desc) { - - if (name.equals("hashCode") && desc.equals("()I")) { - classMeta.setHasEqualsOrHashcode(true); - return true; - } - - if (name.equals("equals") && desc.equals("(Ljava/lang/Object;)Z")) { - classMeta.setHasEqualsOrHashcode(true); - return true; - } - - return false; - } - - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassConstructor.java b/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassConstructor.java deleted file mode 100644 index 4ec0dee13..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassConstructor.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.avaje.ebeaninternal.server.subclass; - -import com.avaje.ebean.enhance.agent.ClassMeta; -import com.avaje.ebean.enhance.agent.EnhanceConstants; -import com.avaje.ebean.enhance.agent.VisitMethodParams; -import com.avaje.ebean.enhance.asm.ClassVisitor; -import com.avaje.ebean.enhance.asm.Label; -import com.avaje.ebean.enhance.asm.MethodVisitor; -import com.avaje.ebean.enhance.asm.Opcodes; - -public class SubClassConstructor implements Opcodes, EnhanceConstants{ - - public static void addDefault(ClassVisitor cv, ClassMeta meta) { - VisitMethodParams params = new VisitMethodParams(cv, Opcodes.ACC_PUBLIC, "", "()V", null, null); - add(params, meta); - } - - public static void add(VisitMethodParams params, ClassMeta meta) { - - String className = meta.getClassName(); - String superClassName = meta.getSuperClassName(); - - if (params.forcePublic()){ - if (meta.isLog(0)){ - meta.log(" forcing ACC_PUBLIC "); - } - } - - MethodVisitor mv = params.visitMethod(); - //mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitLineNumber(17, l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, superClassName, "", "()V"); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitLineNumber(18, l1); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(NEW, C_INTERCEPT); - mv.visitInsn(DUP); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, C_INTERCEPT, "", "(Ljava/lang/Object;)V"); - mv.visitFieldInsn(PUTFIELD, className, INTERCEPT_FIELD, L_INTERCEPT); - Label l2 = new Label(); - mv.visitLabel(l2); - mv.visitLineNumber(19, l2); - mv.visitInsn(RETURN); - Label l3 = new Label(); - mv.visitLabel(l3); - mv.visitLocalVariable("this", "L"+className+";", null, l0, l3, 0); - mv.visitMaxs(4, 1); - mv.visitEnd(); - } -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassFactory.java b/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassFactory.java deleted file mode 100644 index 5ac5c564f..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassFactory.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.avaje.ebeaninternal.server.subclass; - -import java.io.IOException; -import java.io.InputStream; - -import com.avaje.ebean.enhance.agent.ClassPathClassBytesReader; -import com.avaje.ebean.enhance.agent.EnhanceConstants; -import com.avaje.ebean.enhance.agent.EnhanceContext; -import com.avaje.ebean.enhance.asm.ClassReader; -import com.avaje.ebean.enhance.asm.ClassWriter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Creates Classes that implement EntityBean for a given normal bean Class. - *

- * This dynamically creates a subclass of a normal bean class. The subclass has - * method interception to handle the lazy loading of references and old values - * creation. - *

- */ -public class SubClassFactory extends ClassLoader implements EnhanceConstants, GenSuffix { - - private static final Logger logger = LoggerFactory.getLogger(SubClassFactory.class); - - private static final int CLASS_WRITER_FLAGS = ClassWriter.COMPUTE_FRAMES + ClassWriter.COMPUTE_MAXS; - - private final EnhanceContext enhanceContext; - - private final ClassLoader parentClassLoader; - - - /** - * Create with a given ClassLoader. - */ - public SubClassFactory(ClassLoader parent, int logLevel) { - super(parent); - parentClassLoader = parent; - - ClassPathClassBytesReader reader = new ClassPathClassBytesReader(null); - enhanceContext = new EnhanceContext(reader, true, "debug="+logLevel); - } - - /** - * Create a subclass for the given bean class that implements EntityBean interface. - *

- * The transientGetters is a list of getter methods that are considered - * no persistent. That is, when they are called the bean should NOT - * trigger creation of an 'old values' copy of the beans values. - *

- */ - public Class create(Class normalClass, String serverName) throws IOException { - - String subClassSuffix = EnhanceConstants.SUFFIX; - if (serverName != null){ - subClassSuffix += "$"+serverName; - } - - // Note: these have periods rather than slashes - String clsName = normalClass.getName(); - String subClsName = clsName+subClassSuffix; - - try { - byte[] newClsBytes = subclassBytes(clsName, subClassSuffix); - - Class newCls = defineClass(subClsName, newClsBytes, 0, newClsBytes.length); - return newCls; - - } catch (IOException ex){ - String m = "Error creating subclass for ["+clsName+"]"; - logger.error(m, ex); - throw ex; - - } catch (Throwable ex){ - String m = "Error creating subclass for ["+clsName+"]"; - logger.error(m, ex); - throw new RuntimeException(ex); - } - } - - - /** - * Return byte code for the subclass. - *

- * Note that if transientInfo is null, then no interception of getters or setters - * takes place. - *

- */ - private byte[] subclassBytes(String className, String subClassSuffix) - throws IOException { - - String resName = className.replace('.', '/')+".class"; - - InputStream is = getResourceAsStream(resName); - - ClassReader cr = new ClassReader(is); - ClassWriter cw = new ClassWriter(CLASS_WRITER_FLAGS); - - SubClassClassAdpater ca = new SubClassClassAdpater(subClassSuffix, cw, parentClassLoader, enhanceContext); - if (ca.isLog(1)) { - ca.log(" enhancing " + className+subClassSuffix); - } - - cr.accept(ca, 0); - - return cw.toByteArray(); - } -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassGenerator.java b/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassGenerator.java deleted file mode 100644 index 24f21f95c..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassGenerator.java +++ /dev/null @@ -1,253 +0,0 @@ -package com.avaje.ebeaninternal.server.subclass; - - -/** - * Used to generate a subclass based on a bean. - *

- * It does not have the fields or private methods of the read class. It replaces - * the method code with calls to super instead. It may need to add hashCode() - * and equals() methods to make sure a reference is loaded prior to either of - * these methods being called. It uses writeReplace() to modify the - * serialisation. - *

- */ -public class SubClassGenerator {// extends ClassAdapter implements Opcodes, GenConstants { - -// private static final Logger logger = LogFactory.get(SubClassGenerator.class); -// -// boolean isInterceptFieldAdded = false; -// -// boolean isAddClonable = true; -// -// boolean superHasEquals = false; -// -// ClassInfo info; -// -// MethodInfo methodInfo; -// -// boolean hasSuperClass; -// -// /** -// * Create with the ClassInfo. -// */ -// public SubClassGenerator(ClassVisitor cv, ClassInfo info) { -// super(cv); -// this.info = info; -// this.methodInfo = info.getMethodInfo(); -// } -// -// /** -// * Create the class definition replacing the className and super class. -// */ -// public void visit(int version, int access, String name, String signature, String superName, -// String[] interfaces) { -// -// // Note: These have slashes rather than periods!! -// String className = name+info.getSuffix(); -// String superClassName; -// if ("java/lang/Object".endsWith(superName)){ -// superClassName = name; -// } else { -// hasSuperClass = true; -// superClassName = name;//superName+info.getSuffix(); -// } -// -// info.setClassName(className); -// info.setSuperClassName(superClassName); -// -// -// // Note: interfaces can be an empty array but not null -// int n = 1 + interfaces.length; -// String[] c = new String[n]; -// System.arraycopy(interfaces, 0, c, 0, interfaces.length); -// -// // Add the EntityBean interface -// c[c.length - 1] = ENTITYBEAN; -// -// super.visit(version, access, className, signature, superClassName, c); -// } -// -// /** -// * The ebeanIntercept field is added once but thats all. Note the other -// * fields are defined in the superclass. -// */ -// public FieldVisitor visitField(int access, String name, String desc, String signature, -// Object value) { -// -// if (!isInterceptFieldAdded) { -// -// FieldVisitor f0 = cv.visitField(ACC_PRIVATE + ACC_VOLATILE, IDENTITY_FIELD_NAME, "Ljava/lang/Object;", null, null); -// f0.visitEnd(); -// -// FieldVisitor f1 = cv.visitField(0, INTERCEPT_FIELD_NAME, L_INTERCEPT, null, null); -// f1.visitEnd(); -// -// isInterceptFieldAdded = true; -// return null; -// } -// -// return null; -// } -// -// /** -// * Replace the method code with calls to super. Add the intercept code as -// * required. -// */ -// public MethodVisitor visitMethod(int access, String name, String desc, String signature, -// String[] exceptions) { -// -// boolean isPrivate = ((access & Opcodes.ACC_PRIVATE) != 0); -// boolean isStatic = ((access & Opcodes.ACC_STATIC) != 0); -// if (isPrivate || isStatic) { -// // no intercept on static or private methods -// return null; -// } -// // the key to look up in methodInfo -// String methodKey = name + ":" + desc; -// -// if (hasSuperClass){ -// if (logger.isTraceEnabled()){ -// String msg = "existing methods "+info.getClassName()+" "+methodKey; -// logger.trace(msg); -// } -// } -// -// VisitMethodParams params = new VisitMethodParams(cv, access, name, desc, signature, exceptions); -// -// if (methodInfo.isSet(methodKey)) { -// // for persistent properties excluding assoc Many's & id -// // ie. Old values not created for id or assoc many. -// return new ProxySetterMethod(params, info, methodInfo); -// } -// -// if (methodInfo.isGet(methodKey)) { -// // for persistent properties excluding id properties. -// // ie. reference loading not fired for id properties. -// return new ProxyGetterMethod(params, info); -// } -// -// if ("".equals(name)) { -// return new ProxyConstructor(params, info); -// } -// -// if ("hashCode:()I".equals(methodKey)) { -// return new ProxyMethod(params, info); -// } -// -// if ("clone:()Ljava/lang/Object;".equals(methodKey)) { -// // SuperClass has a clone() method -// isAddClonable = false; -// return new MethodClone(params, info); -// } -// -// if ("toString:()Ljava/lang/String;".equals(methodKey)) { -// // No intercept on toString() as used by debuggers etc -// return null; -// } -// if ("hashCode:()I".equals(methodKey)) { -// return null; -// } -// if ("equals:(Ljava/lang/Object;)Z".equals(methodKey)) { -// superHasEquals = true; -// return null; -// } -// -// return null; -// } -// -// /** -// * Add methods to get and set the entityBeanIntercept. Also add the -// * writeReplace method to control serialisation. -// */ -// public void visitEnd() { -// -// if (isAddClonable){ -// // super has not overwritten the clone() method. -// // we will add the clone() method in case a super of the super has clone() -// String[] exceptions = new String[] { "java/lang/CloneNotSupportedException" }; -// VisitMethodParams params = new VisitMethodParams(cv, ACC_PUBLIC, "clone", "()Ljava/lang/Object;", null, exceptions); -// MethodClone methodClone = new MethodClone(params, info); -// methodClone.visitCode(); -// } -// -// MethodInfo methodInfo = info.getMethodInfo(); -// if (methodInfo.isEmbedded()){ -// // don't override equals etc when it is an embedded bean -// // Either EmbeddedId or a Embeddable -// -// } else if (methodInfo.overrideEquals(superHasEquals)) { -// // we want to generate a equals() hashCode() and ebeanGetIndentity() -// // methods so that the generated subclass has built in equals() support. -// -// if (methodInfo.getIdGetter() == null) { -// if (methodInfo.isSqlSelectBased()){ -// // This could be common for reporting type beans based on -// // sql-select that use group by type queries. -// } else { -// String m = "Can not generate equals for ["+info.getClassName(); -// m += "]. Concatinated id?"; -// logger.warn(m); -// } -// } else { -// -// if (generateEbeanGetIdentityMethod()){ -// // add equals() -// MethodEquals.add(cv, info); -// -// // add hashCode() -// MethodHashCode.add(cv, info); -// } -// } -// } -// -// // add additional getters from super class inheritance -// List additionalGetters = methodInfo.getAdditionalGetters(); -// for (MethodDesc methodDesc : additionalGetters) { -// VisitMethodParams params = new VisitMethodParams(cv, ACC_PUBLIC, methodDesc); -// ProxyGetterMethod getter = new ProxyGetterMethod(params, info); -// getter.visitCode(); -// } -// -// // add additional setters from super class inheritance -// List additionalSetters = methodInfo.getAdditionalSetters(); -// for (MethodDesc methodDesc : additionalSetters) { -// VisitMethodParams params = new VisitMethodParams(cv, ACC_PUBLIC, methodDesc); -// ProxySetterMethod setter = new ProxySetterMethod(params, info, methodInfo); -// setter.visitCode(); -// } -// -// // add set get methods for ebeanIntecept -// MethodGetSetIntercept.add(cv, info); -// -// // add a writeReplace method to control serialisation -// MethodWriteReplace.add(cv, info); -// -// super.visitEnd(); -// } -// -// private boolean generateEbeanGetIdentityMethod() { -// String idGetterDesc = methodInfo.getIdGetterDesc(); -// if (idGetterDesc.equals("()I")) { -// // int version of ebeanGetIndentity() -// MethodEbeanGetIdentityInt.add(cv, info); -// return true; -// -// } else if (idGetterDesc.equals("()J")) { -// // long version of ebeanGetIndentity() -// MethodEbeanGetIdentityLong.add(cv, info); -// return true; -// -// } else if (idGetterDesc.length() > 5) { -// // Object version of ebeanGetIndentity() -// MethodEbeanGetIdentity.add(cv, info); -// return true; -// -// } else { -// String m = "Can not generate equals for ["+info.getClassName(); -// m += "] due to type of id property: "+idGetterDesc; -// logger.warn(m); -// return false; -// } -// } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassManager.java b/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassManager.java deleted file mode 100644 index 33d4009f6..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassManager.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.avaje.ebeaninternal.server.subclass; - -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.concurrent.ConcurrentHashMap; - -import javax.persistence.PersistenceException; - -import com.avaje.ebean.config.ServerConfig; -import com.avaje.ebean.enhance.agent.EnhanceConstants; -import com.avaje.ebeaninternal.api.ClassUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Creates and caches the dynamically generated subclasses. - *

- * That is, the 'EntityBean' classes are dynamically generated subclasses of the - * 'vanilla' classes. - *

- */ -public class SubClassManager implements EnhanceConstants { - - private static final Logger logger = LoggerFactory.getLogger(SubClassManager.class); - - private final ConcurrentHashMap> clzMap; - - private final SubClassFactory subclassFactory; - - private final String serverName; - - /** - * The log level for debugging subclass generation/enhancement. - */ - private final int logLevel; - - /** - * Construct with the ClassLoader used to load Ebean.class. - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public SubClassManager(ServerConfig serverConfig) { - - String s = serverConfig.getProperty("subClassManager.preferContextClassloader", "true"); - final boolean preferContext = "true".equalsIgnoreCase(s); - - this.serverName = serverConfig.getName(); - this.logLevel = serverConfig.getEnhanceLogLevel(); - this.clzMap = new ConcurrentHashMap>(); - - try { - subclassFactory = (SubClassFactory) AccessController - .doPrivileged(new PrivilegedExceptionAction() { - public Object run() { - ClassLoader cl = ClassUtil.getClassLoader(this.getClass(), preferContext); - logger.info("SubClassFactory parent ClassLoader ["+cl.getClass().getName()+"]"); - return new SubClassFactory(cl, logLevel); - } - }); - } catch (PrivilegedActionException e) { - throw new PersistenceException(e); - } - } - - /** - * Resolve the Class for the class name. - *

- * The methodInfo is used to determine the method interception on the - * generated class. - *

- *

- * If the class has already been generated then it is returned out of a - * cache. - *

- */ - public Class resolve(String name) { - - synchronized (this) { - String superName = SubClassUtil.getSuperClassName(name); - Class clz = clzMap.get(superName); - if (clz == null) { - clz = createClass(superName); - clzMap.put(superName, clz); - } - return clz; - } - } - - private Class createClass(String name) { - - try { - - Class superClass = Class.forName(name, true, subclassFactory.getParent()); - - return subclassFactory.create(superClass, serverName); - - } catch (Exception ex) { - String m = "Error creating subclass for [" + name + "]"; - throw new PersistenceException(m, ex); - } - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassUtil.java b/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassUtil.java deleted file mode 100644 index d8ca991f0..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/subclass/SubClassUtil.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.avaje.ebeaninternal.server.subclass; - - -/** - * Helper methods for generated sub classes. - */ -public class SubClassUtil implements GenSuffix { - - /** - * Return true if this is a generated class. - */ - public static boolean isSubClass(String className) { - - return (className.lastIndexOf(SUFFIX) != -1); - } - - /** - * Return the super class name given the generated className. - */ - public static String getSuperClassName(String className){ - int dPos = className.lastIndexOf(SUFFIX); - if (dPos > -1){ - return className.substring(0, dPos); - } - return className; - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/subclass/package.html b/src/main/java/com/avaje/ebeaninternal/server/subclass/package.html deleted file mode 100644 index e16d9d55d..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/subclass/package.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - Used to generate subclasses rather than weaving - - -Used to generate subclasses rather than weaving -

-As alternative to weaving/enhancing the classes via javaagent or ant you -can use dynamically generated subclasses. These objects support that feature. -

- - - - \ No newline at end of file diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultPersistenceContext.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultPersistenceContext.java index a20db7c3d..1c8ef9228 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultPersistenceContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultPersistenceContext.java @@ -7,7 +7,6 @@ import java.util.Map.Entry; import com.avaje.ebean.bean.PersistenceContext; import com.avaje.ebeaninternal.api.Monitor; -import com.avaje.ebeaninternal.server.subclass.SubClassUtil; /** * Default implementation of PersistenceContext. @@ -120,9 +119,7 @@ public final class DefaultPersistenceContext implements PersistenceContext { private ClassContext getClassContext(Class beanType) { - // strip off $$EntityBean.. suffix... - String clsName = SubClassUtil.getSuperClassName(beanType.getName()); - + String clsName = beanType.getName(); ClassContext classMap = typeCache.get(clsName); if (classMap == null) { classMap = new ClassContext(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionManager.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionManager.java index 2d9eba81e..bf638fadd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionManager.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionManager.java @@ -294,6 +294,10 @@ public class TransactionManager { c.setTransactionIsolation(isolationLevel); } + if (explicit && TXN_LOGGER.isTraceEnabled()) { + TXN_LOGGER.trace(t.getLogPrefix()+"Begin"); + } + return t; } catch (SQLException ex) { @@ -371,6 +375,9 @@ public class TransactionManager { public void notifyOfQueryOnly(boolean onCommit, SpiTransaction transaction, Throwable cause) { // Nothing that interesting here + if (TXN_LOGGER.isTraceEnabled()) { + TXN_LOGGER.trace(transaction.getLogPrefix()+"Commit - query only"); + } } private String formatThrowable(Throwable e){ diff --git a/src/test/java/com/avaje/ebean/enhance/agent/TestTransformConstruct.java b/src/test/java/com/avaje/ebean/enhance/agent/TestTransformConstruct.java deleted file mode 100644 index 8f91f555f..000000000 --- a/src/test/java/com/avaje/ebean/enhance/agent/TestTransformConstruct.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.avaje.ebean.enhance.agent; - -import junit.framework.Assert; -import junit.framework.TestCase; - -public class TestTransformConstruct extends TestCase { - - - public void test() { - - Transformer t = new Transformer("", ""); - Assert.assertNotNull(t); - - t = new Transformer("d", ""); - Assert.assertNotNull(t); - - t = new Transformer("dd", ""); - Assert.assertNotNull(t); - - t = new Transformer((String)null, null); - Assert.assertNotNull(t); - - } - -} diff --git a/src/test/java/com/avaje/tests/basic/TestSerialization.java b/src/test/java/com/avaje/tests/basic/TestSerialization.java deleted file mode 100644 index 3d81b4624..000000000 --- a/src/test/java/com/avaje/tests/basic/TestSerialization.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.avaje.tests.basic; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.sql.Date; -import java.util.ArrayList; -import java.util.List; - -import junit.framework.Assert; -import junit.framework.TestCase; - -import com.avaje.ebean.Ebean; -import com.avaje.ebean.EbeanServer; -import com.avaje.ebean.bean.EntityBean; -import com.avaje.ebean.bean.EntityBeanIntercept; -import com.avaje.ebean.bean.SerializeControl; -import com.avaje.ebean.common.BeanList; -import com.avaje.tests.model.basic.Customer; -import com.avaje.tests.model.basic.Order; -import com.avaje.tests.model.basic.Order.Status; -import com.avaje.tests.model.basic.OrderDetail; - -public class TestSerialization extends TestCase { - - public void testSerialization() { - - EbeanServer server = Ebean.getServer(null); - - Customer customer = server.getReference(Customer.class, 1); - - Order o = server.createEntityBean(Order.class); - o.setOrderDate(new Date(System.currentTimeMillis())); - o.setStatus(Status.NEW); - o.setCustomer(customer); - - BeanList details = new BeanList(); - o.setDetails(details); - - EntityBean eb = (EntityBean)o; - - Order orderCopy = (Order)eb._ebean_createCopy(); - - Assert.assertNotNull(orderCopy.getDetails()); - Assert.assertNotNull(orderCopy.getCustomer()); - - EntityBeanIntercept ebi = eb._ebean_getIntercept(); - o.setStatus(Status.APPROVED); - - ebi.setReadOnly(true); - ebi.setLoaded(); - - try { - o.setStatus(Status.COMPLETE); - Assert.assertTrue("dont get here",false); - } catch (IllegalStateException e){ - Assert.assertTrue("throws exception",true); - } - - SerializeControl.setVanilla(true); - Assert.assertTrue(SerializeControl.isVanillaBeans()); - Assert.assertTrue(SerializeControl.isVanillaCollections()); - - Order testUsingSubclassing = new Order(); - if (testUsingSubclassing instanceof EntityBean){ - System.out.println("Need to run serialisation test with 'subclassing/proxies'"); - - } else { - System.out.println("Testing serialisation of 'subclassing/proxies'"); - Object vanillaOrder = serialWriteRead(o, true); - Assert.assertFalse("should be an EntityBean", (vanillaOrder instanceof EntityBean)); - Assert.assertTrue("should be an Order", (vanillaOrder instanceof Order)); - - Order vanOrder = (Order)vanillaOrder; - Customer vanCustomer = vanOrder.getCustomer(); - List vanDetails = vanOrder.getDetails(); - - Assert.assertFalse("should NOT be an EntityBean", (vanCustomer instanceof EntityBean)); - Assert.assertFalse("should NOT be an BeanList", (vanDetails instanceof BeanList)); - Assert.assertTrue("should be an ArrayList", (vanDetails instanceof ArrayList)); - Assert.assertTrue("should be an Customer", (vanCustomer instanceof Customer)); - } - - SerializeControl.setVanilla(false); - - Object subclassOrder = serialWriteRead(o, false); - Assert.assertTrue("should be an Order", (subclassOrder instanceof Order)); - Assert.assertTrue("should be an EntityBean", (subclassOrder instanceof EntityBean)); - - SerializeControl.setVanilla(true); - - File serTestFile = new File("serTest"); - if (serTestFile.exists()){ - serTestFile.delete(); - } - } - - private Object serialWriteRead(Object inputObject, boolean vanilla){ - - try { - - - - File serTestFile = new File("serTest"); - FileOutputStream fout = new FileOutputStream(serTestFile); - ObjectOutputStream oos = new ObjectOutputStream(fout); - - oos.writeObject(inputObject); - oos.close(); - - FileInputStream fin = new FileInputStream(serTestFile); - - ObjectInputStream ois; - if (vanilla){ - ois = new ObjectInputStream(fin); - } else { - ois = Ebean.getServer(null).createProxyObjectInputStream(fin); - } - Object readObject = ois.readObject(); - ois.close(); - return readObject; - - } catch (Exception e){ - e.printStackTrace(); - Assert.assertTrue(false); - return null; - } - - } - -} diff --git a/src/test/java/com/avaje/tests/basic/TestTransientInternalFields.java b/src/test/java/com/avaje/tests/basic/TestTransientInternalFields.java deleted file mode 100644 index 5fb80dbaf..000000000 --- a/src/test/java/com/avaje/tests/basic/TestTransientInternalFields.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.avaje.tests.basic; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.List; - -import junit.framework.Assert; -import junit.framework.TestCase; - -import com.avaje.ebean.Ebean; -import com.avaje.ebean.bean.EntityBean; -import com.avaje.ebean.bean.EntityBeanIntercept; -import com.avaje.tests.model.basic.Customer; -import com.avaje.tests.model.basic.ResetBasicData; - -public class TestTransientInternalFields extends TestCase { - - public void test() { - - ResetBasicData.reset(); - - List list = Ebean.find(Customer.class).findList(); - - Customer c = list.get(0); - - Object back = serialWriteRead(c, false); - - if (back instanceof EntityBean){ - EntityBean entityBean = (EntityBean)back; - EntityBeanIntercept ebi = entityBean._ebean_getIntercept(); - if (ebi == null){ - ebi = entityBean._ebean_intercept(); - Assert.assertNotNull(ebi); - } - } - - File serTestFile = new File("serTransTest"); - if (serTestFile.exists()){ - serTestFile.delete(); - } - } - - private Object serialWriteRead(Object inputObject, boolean vanilla){ - - try { - - File serTestFile = new File("serTransTest"); - FileOutputStream fout = new FileOutputStream(serTestFile); - ObjectOutputStream oos = new ObjectOutputStream(fout); - - oos.writeObject(inputObject); - oos.close(); - - FileInputStream fin = new FileInputStream(serTestFile); - - ObjectInputStream ois; - if (vanilla){ - ois = new ObjectInputStream(fin); - } else { - ois = Ebean.getServer(null).createProxyObjectInputStream(fin); - } - Object readObject = ois.readObject(); - ois.close(); - return readObject; - - } catch (Exception e){ - e.printStackTrace(); - Assert.assertTrue(false); - return null; - } - - } -} diff --git a/src/test/java/com/avaje/tests/basic/vanilla/TestVanillaQuery.java b/src/test/java/com/avaje/tests/basic/vanilla/TestVanillaQuery.java deleted file mode 100644 index 4aef76878..000000000 --- a/src/test/java/com/avaje/tests/basic/vanilla/TestVanillaQuery.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.avaje.tests.basic.vanilla; - -import java.util.List; - -import junit.framework.Assert; -import junit.framework.TestCase; - -import com.avaje.ebean.Ebean; -import com.avaje.ebean.bean.EntityBean; -import com.avaje.ebean.config.GlobalProperties; -import com.avaje.tests.model.basic.Order; -import com.avaje.tests.model.basic.ResetBasicData; - -public class TestVanillaQuery extends TestCase { - - - public void test() { - - Order beanEnhancedCheck = new Order(); - - if (beanEnhancedCheck instanceof EntityBean){ - // test only real when not using enhancement - System.out.println("Not testing TestVanillaQuery as beans are enhanced"); - return; - } - - // These settings only work when test run standalone (Ebean not booted yet) - GlobalProperties.put("ebean.vanillaMode", "true"); - GlobalProperties.put("ebean.vanillaRefMode", "true"); - - // actually only a vanilla class when using subclass generation - Class vanillaClass = Order.class; - -// // ONLY Testing this when running test manually/standalone at this stage -// Order oref = Ebean.getReference(Order.class, 1); -// Class refClass = oref.getClass(); -// Assert.assertEquals(vanillaClass, refClass); - - ResetBasicData.reset(); - - List list = - Ebean.find(Order.class) - .fetch("details") - .setVanillaMode(true) - .findList(); - - Assert.assertTrue(list.size() > 0); - - Order o = list.get(0); - - // actually only a vanilla class when using subclass generation - Class returnedClass = o.getClass(); - Assert.assertEquals(vanillaClass, returnedClass); - - Ebean.refreshMany(o, "details"); - - Ebean.refresh(o); - - if (!(o instanceof EntityBean)){ - // using subclass generation ... - list = - Ebean.find(Order.class) - .setVanillaMode(false) - .findList(); - - Class entityBeanClass = list.get(0).getClass(); - - Assert.assertNotSame(vanillaClass, entityBeanClass); - } - } -} diff --git a/src/test/java/com/avaje/tests/model/basic/xtra/DummyDao.java b/src/test/java/com/avaje/tests/model/basic/xtra/DummyDao.java index 4abbd7062..bba947a8f 100644 --- a/src/test/java/com/avaje/tests/model/basic/xtra/DummyDao.java +++ b/src/test/java/com/avaje/tests/model/basic/xtra/DummyDao.java @@ -4,19 +4,32 @@ import java.util.List; import javax.persistence.EntityNotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.avaje.ebean.Ebean; +import com.avaje.ebean.Transaction; import com.avaje.ebean.TxType; import com.avaje.ebean.annotation.Transactional; public class DummyDao { + Logger logger = LoggerFactory.getLogger(DummyDao.class); + @Transactional(type = TxType.REQUIRES_NEW) public void doSomething() { - System.out.println("Hello World"); + logger.info(" --- in DummyDao.doSomething() with TxType.REQUIRES_NEW"); + Transaction txn = Ebean.currentTransaction(); + if (txn == null) { + logger.error(" NO TRANSACTION ??"); + } else { + logger.info(" --- txn - "+txn); + } + } @Transactional - // ebean transactional annotation, not spring transactional annotation public void addToObject(Long id, Double anotherNumber, List ids) throws EntityNotFoundException { // and more code } diff --git a/src/test/java/com/avaje/tests/unitinternal/TestTxTypeOnTransactional.java b/src/test/java/com/avaje/tests/unitinternal/TestTxTypeOnTransactional.java index 8b256589c..5f1398468 100644 --- a/src/test/java/com/avaje/tests/unitinternal/TestTxTypeOnTransactional.java +++ b/src/test/java/com/avaje/tests/unitinternal/TestTxTypeOnTransactional.java @@ -5,6 +5,8 @@ import javax.persistence.OptimisticLockException; import junit.framework.TestCase; import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.avaje.ebean.Ebean; import com.avaje.ebean.Transaction; @@ -14,30 +16,35 @@ import com.avaje.tests.model.basic.xtra.OptimisticLockExceptionThrowingDao; public class TestTxTypeOnTransactional extends TestCase { - public void test() { - - DummyDao dao = new DummyDao(); - dao.doSomething(); + Logger logger = LoggerFactory.getLogger(TestTxTypeOnTransactional.class); + + public void test() { + + logger.info("-- test pre dao.doSomething"); + DummyDao dao = new DummyDao(); + dao.doSomething(); + logger.info("-- test post dao.doSomething"); + } + + public void testOptimisticException() { + + logger.info("-- testOptimisticException"); + EBasicVer v = new EBasicVer(); + v.setName("occ"); + v.setDescription("blah"); + Ebean.save(v); + + logger.info("-- OptimisticLockExceptionThrowingDao"); + OptimisticLockExceptionThrowingDao dao = new OptimisticLockExceptionThrowingDao(); + try { + dao.doSomething(v); + // never get here + Assert.assertTrue(false); + } catch (OptimisticLockException e) { + Transaction inMethodTransaction = dao.getInMethodTransaction(); + boolean active = inMethodTransaction.isActive(); + Assert.assertFalse(active); } - - public void testOptimisticException() { - - EBasicVer v = new EBasicVer(); - v.setName("occ"); - v.setDescription("blah"); - Ebean.save(v); - - - OptimisticLockExceptionThrowingDao dao = new OptimisticLockExceptionThrowingDao(); - try { - dao.doSomething(v); - // never get here - Assert.assertTrue(false); - } catch (OptimisticLockException e){ - Transaction inMethodTransaction = dao.getInMethodTransaction(); - boolean active = inMethodTransaction.isActive(); - Assert.assertFalse(active); - } - } - + } + } diff --git a/src/test/java/com/avaje/tests/update/TestStatelessUpdate.java b/src/test/java/com/avaje/tests/update/TestStatelessUpdate.java index 15c293413..552ec0784 100644 --- a/src/test/java/com/avaje/tests/update/TestStatelessUpdate.java +++ b/src/test/java/com/avaje/tests/update/TestStatelessUpdate.java @@ -24,12 +24,12 @@ public class TestStatelessUpdate extends TestCase { server.save(e); - EBasic updateName = new EBasic(); - updateName.setId(e.getId()); - updateName.setName("justName"); - - - server.update(updateName, null, null, false, false); +// EBasic updateName = new EBasic(); +// updateName.setId(e.getId()); +// updateName.setName("justName"); +// +// +// server.update(updateName, null, null, false, false); EBasic updateAll = new EBasic(); updateAll.setId(e.getId()); diff --git a/src/test/java/com/avaje/tests/xml/runtime/XoiNode.java b/src/test/java/com/avaje/tests/xml/runtime/XoiNode.java index 5a6819967..b1ced6da7 100644 --- a/src/test/java/com/avaje/tests/xml/runtime/XoiNode.java +++ b/src/test/java/com/avaje/tests/xml/runtime/XoiNode.java @@ -9,7 +9,7 @@ public interface XoiNode { public String getNodeName(); - public Object createBean(boolean vanillaMode); + public Object createBean(); public void writeNode(XrOutputDocument out, Node node, Object bean) throws IOException; diff --git a/src/test/java/com/avaje/tests/xml/runtime/XrCollection.java b/src/test/java/com/avaje/tests/xml/runtime/XrCollection.java index a195fa4ec..a15bb27bd 100644 --- a/src/test/java/com/avaje/tests/xml/runtime/XrCollection.java +++ b/src/test/java/com/avaje/tests/xml/runtime/XrCollection.java @@ -59,14 +59,14 @@ public class XrCollection extends XrNode implements XoiNode { Object parentBean = ctx.getBean(); // create a List/Set/Map to hold the details - Object details = manyProp.createEmpty(ctx.isVanillaMode()); + Object details = manyProp.createEmpty(false); // Wrapper used to add to the collection BeanCollectionAdd bcAdd = manyProp.getBeanCollectionAdd(details, mapKey); Node detailNode = nextElement(node.getFirstChild()); do { - Object detailBean = targetDescriptor.createBean(ctx.isVanillaMode()); + Object detailBean = targetDescriptor.createBean(); ctx.setBean(detailBean); for (int i = 0; i < childNodes.length; i++) { diff --git a/src/test/java/com/avaje/tests/xml/runtime/XrContext.java b/src/test/java/com/avaje/tests/xml/runtime/XrContext.java index 02b43b588..9bea9e192 100644 --- a/src/test/java/com/avaje/tests/xml/runtime/XrContext.java +++ b/src/test/java/com/avaje/tests/xml/runtime/XrContext.java @@ -40,7 +40,7 @@ public class XrContext implements OxmContext { XoiNode xoiNode = getXoiNode(node.getNodeName()); - Object bean = xoiNode.createBean(false); + Object bean = xoiNode.createBean(); XrReadContext ctx = new XrReadContext(bean); diff --git a/src/test/java/com/avaje/tests/xml/runtime/XrNode.java b/src/test/java/com/avaje/tests/xml/runtime/XrNode.java index 934919600..560b49b98 100644 --- a/src/test/java/com/avaje/tests/xml/runtime/XrNode.java +++ b/src/test/java/com/avaje/tests/xml/runtime/XrNode.java @@ -61,8 +61,8 @@ public class XrNode extends XrBase implements XoiNode { return nodeName; } - public Object createBean(boolean vanillaMode) { - return beanDescriptor.createBean(vanillaMode); + public Object createBean() { + return beanDescriptor.createBean(); } public String getNodeName() { @@ -74,7 +74,7 @@ public class XrNode extends XrBase implements XoiNode { Object parentBean = null; if (assocBeanValue){ parentBean = ctx.getBean(); - Object childBean = beanDescriptor.createBean(ctx.isVanillaMode()); + Object childBean = beanDescriptor.createBean(); setObjectValue(parentBean, childBean); ctx.setBean(childBean); diff --git a/src/test/java/com/avaje/tests/xml/runtime/XrReadContext.java b/src/test/java/com/avaje/tests/xml/runtime/XrReadContext.java index c70853752..c69b89241 100644 --- a/src/test/java/com/avaje/tests/xml/runtime/XrReadContext.java +++ b/src/test/java/com/avaje/tests/xml/runtime/XrReadContext.java @@ -2,8 +2,6 @@ package com.avaje.tests.xml.runtime; public class XrReadContext { - private boolean vanillaMode; - private Object bean; public XrReadContext(Object bean) { @@ -17,13 +15,4 @@ public class XrReadContext { public void setBean(Object bean) { this.bean = bean; } - - public boolean isVanillaMode() { - return vanillaMode; - } - - public void setVanillaMode(boolean vanillaMode) { - this.vanillaMode = vanillaMode; - } - } diff --git a/src/test/resources/ebean.properties b/src/test/resources/ebean.properties index 032535031..1fa52633c 100644 --- a/src/test/resources/ebean.properties +++ b/src/test/resources/ebean.properties @@ -88,7 +88,7 @@ datasource.h2.databaseUrl=jdbc:h2:mem:tests;DB_CLOSE_DELAY=-1 datasource.h2.databaseDriver=org.h2.Driver datasource.h2.minConnections=1 datasource.h2.maxConnections=25 -datasource.h2.heartbeatsql=select 1 +#datasource.h2.heartbeatsql=select 1 datasource.h2.isolationlevel=read_committed datasource.h2.capturestacktrace=true datasource.h2.maxStackTraceSize=20 diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index cc3d9ef66..68108fe96 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -32,5 +32,8 @@ + + +
\ No newline at end of file