From 2567022d954e73b74b18a0d3754bdcd425254f3a Mon Sep 17 00:00:00 2001
From: Robin Bygrave
- * 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.
- *
- * 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)}.
- *
- * This is not used when entity bean classes are enhanced via javaagent or ant
- * etc - only when a subclass is generated.
- *
- * 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.
- *
- * 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
@@ -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
- * 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- * Used for EmbeddedId Bean construction. - *
- */ - public Object createVanillaBean() { - return beanReflect.createVanillaBean(); + public Object createBean() { + return createEntityBean(); } /** @@ -1341,9 +1331,9 @@ public class BeanDescriptor- * 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
- * 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("- * 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 ("- * 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- * 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 @@ - - - --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