diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/EnhancementException.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/EnhancementException.java
new file mode 100644
index 0000000000..2955cbcec6
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/EnhancementException.java
@@ -0,0 +1,39 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.bytecode.enhance;
+
+import org.hibernate.HibernateException;
+
+/**
+ * @author Steve Ebersole
+ */
+public class EnhancementException extends HibernateException {
+ public EnhancementException(String message) {
+ super( message );
+ }
+
+ public EnhancementException(String message, Throwable root) {
+ super( message, root );
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/EnhancementContext.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/EnhancementContext.java
new file mode 100644
index 0000000000..426972a83d
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/EnhancementContext.java
@@ -0,0 +1,34 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.bytecode.enhance.spi;
+
+import java.security.ProtectionDomain;
+
+/**
+ * @author Steve Ebersole
+ */
+public interface EnhancementContext {
+ public boolean isEntityClass(String className);
+ public boolean isCompositeClass(String className);
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/Enhancer.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/Enhancer.java
new file mode 100644
index 0000000000..94a2cf29de
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/Enhancer.java
@@ -0,0 +1,246 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.bytecode.enhance.spi;
+
+import javax.persistence.Transient;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtNewMethod;
+import javassist.bytecode.AnnotationsAttribute;
+import javassist.bytecode.ConstPool;
+import javassist.bytecode.FieldInfo;
+import javassist.bytecode.annotation.Annotation;
+
+import org.jboss.logging.Logger;
+
+import org.hibernate.HibernateException;
+import org.hibernate.bytecode.enhance.EnhancementException;
+import org.hibernate.bytecode.internal.javassist.FieldHandled;
+import org.hibernate.engine.ManagedComposite;
+import org.hibernate.engine.ManagedEntity;
+import org.hibernate.engine.spi.EntityEntry;
+import org.hibernate.internal.CoreMessageLogger;
+
+/**
+ * @author Steve Ebersole
+ * @author Jason Greene
+ */
+public class Enhancer {
+ private static final CoreMessageLogger log = Logger.getMessageLogger( CoreMessageLogger.class, Enhancer.class.getName() );
+
+ public static final String ENTITY_ENTRY_FIELD_NAME = "$hibernate_entityEntryHolder";
+ public static final String ENTITY_ENTRY_GETTER_NAME = "hibernate_getEntityEntry";
+ public static final String ENTITY_ENTRY_SETTER_NAME = "hibernate_setEntityEntry";
+
+ private final EnhancementContext enhancementContext;
+
+ private final ClassPool classPool;
+ private final CtClass managedEntityCtClass;
+ private final CtClass managedCompositeCtClass;
+ private final CtClass entityEntryCtClass;
+
+ public Enhancer(EnhancementContext enhancementContext) {
+ this.enhancementContext = enhancementContext;
+
+ this.classPool = new ClassPool( false );
+ try {
+ // add ManagedEntity contract
+ this.managedEntityCtClass = classPool.makeClass(
+ ManagedEntity.class.getClassLoader().getResourceAsStream(
+ ManagedEntity.class.getName().replace( '.', '/' ) + ".class"
+ )
+ );
+
+ // add ManagedEntity contract
+ this.managedCompositeCtClass = classPool.makeClass(
+ ManagedComposite.class.getClassLoader().getResourceAsStream(
+ ManagedComposite.class.getName().replace( '.', '/' ) + ".class"
+ )
+ );
+
+ // "add" EntityEntry
+ this.entityEntryCtClass = classPool.makeClass( EntityEntry.class.getName() );
+ }
+ catch (IOException e) {
+ throw new EnhancementException( "Could not prepare Javassist ClassPool", e );
+ }
+ }
+
+ /**
+ * Performs the enhancement.
+ *
+ * @param className The name of the class whose bytecode is being enhanced.
+ * @param originalBytes The class's original (pre-enhancement) byte code
+ *
+ * @return The enhanced bytecode. Could be the same as the original bytecode if the original was
+ * already enhanced or we could not enhance it for some reason.
+ *
+ * @throws EnhancementException
+ */
+ public byte[] enhance(String className, byte[] originalBytes) throws EnhancementException {
+ final CtClass managedCtClass;
+ try {
+ managedCtClass = classPool.makeClassIfNew( new ByteArrayInputStream( originalBytes ) );
+ }
+ catch (IOException e) {
+ log.unableToBuildEnhancementMetamodel( className );
+ return originalBytes;
+ }
+
+ enhance( managedCtClass );
+
+ DataOutputStream out = null;
+ try {
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ out = new DataOutputStream( byteStream );
+ managedCtClass.toBytecode( out );
+ return byteStream.toByteArray();
+ }
+ catch (Exception e) {
+ log.unableToTransformClass( e.getMessage() );
+ throw new HibernateException( "Unable to transform class: " + e.getMessage() );
+ }
+ finally {
+ try {
+ if ( out != null ) {
+ out.close();
+ }
+ }
+ catch (IOException e) {
+ //swallow
+ }
+ }
+ }
+
+ private void enhance(CtClass managedCtClass) {
+ final String className = managedCtClass.getName();
+ log.debugf( "Enhancing %s", className );
+
+ // can't effectively enhance interfaces
+ if ( managedCtClass.isInterface() ) {
+ log.debug( "skipping enhancement : interface" );
+ return;
+ }
+
+ // skip already enhanced classes
+
+ final String[] interfaceNames = managedCtClass.getClassFile2().getInterfaces();
+ for ( String interfaceName : interfaceNames ) {
+ if ( FieldHandled.class.getName().equals( interfaceName ) ) {
+ log.debug( "skipping enhancement : already enhanced" );
+ return;
+ }
+ }
+
+ if ( enhancementContext.isEntityClass( className ) ) {
+ enhanceAsEntity( managedCtClass );
+ }
+ else if ( enhancementContext.isCompositeClass( className ) ) {
+ enhanceAsComposite( managedCtClass );
+ }
+ else {
+ log.debug( "skipping enhancement : not entity or composite" );
+ }
+ }
+
+ private void enhanceAsEntity(CtClass managedCtClass) {
+ final ConstPool constPool = managedCtClass.getClassFile().getConstPool();
+
+ // add the ManagedEntity interface
+ managedCtClass.addInterface( managedEntityCtClass );
+
+ // add field to hold EntityEntry
+ final CtField entityEntryField;
+ try {
+ entityEntryField = new CtField( entityEntryCtClass, ENTITY_ENTRY_FIELD_NAME, managedCtClass );
+ managedCtClass.addField( entityEntryField );
+ }
+ catch (CannotCompileException e) {
+ throw new EnhancementException(
+ String.format(
+ "Could not enhance entity class [%s] to add field for holding EntityEntry",
+ managedCtClass.getName()
+ ),
+ e
+ );
+ }
+
+ // make that new field @Transient
+ AnnotationsAttribute annotationsAttribute = getVisibleAnnotations( entityEntryField.getFieldInfo() );
+ annotationsAttribute.addAnnotation( new Annotation( Transient.class.getName(), constPool ) );
+
+ // add the ManagedEntity#hibernate_getEntityEntry method
+ try {
+ managedCtClass.addMethod(
+ CtNewMethod.getter( ENTITY_ENTRY_GETTER_NAME, entityEntryField )
+ );
+ }
+ catch (CannotCompileException e) {
+ throw new EnhancementException(
+ String.format(
+ "Could not enhance entity class [%s] to add EntityEntry getter",
+ managedCtClass.getName()
+ ),
+ e
+ );
+ }
+
+ // add the ManagedEntity#hibernate_setEntityEntry method
+ try {
+ managedCtClass.addMethod(
+ CtNewMethod.setter( ENTITY_ENTRY_SETTER_NAME, entityEntryField )
+ );
+ }
+ catch (CannotCompileException e) {
+ throw new EnhancementException(
+ String.format(
+ "Could not enhance entity class [%s] to add EntityEntry setter",
+ managedCtClass.getName()
+ ),
+ e
+ );
+ }
+ }
+
+ private AnnotationsAttribute getVisibleAnnotations(FieldInfo fieldInfo) {
+ AnnotationsAttribute annotationsAttribute = (AnnotationsAttribute) fieldInfo.getAttribute( AnnotationsAttribute.visibleTag );
+ if ( annotationsAttribute == null ) {
+ annotationsAttribute = new AnnotationsAttribute( fieldInfo.getConstPool(), AnnotationsAttribute.visibleTag );
+ fieldInfo.addAttribute( annotationsAttribute );
+ }
+ return annotationsAttribute;
+ }
+
+ private void enhanceAsComposite(CtClass classFile) {
+ }
+
+
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/Managed.java b/hibernate-core/src/main/java/org/hibernate/engine/Managed.java
new file mode 100644
index 0000000000..e822877a10
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/Managed.java
@@ -0,0 +1,34 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.engine;
+
+/**
+ * Contract for classes (specifically, entities and components/embeddables) that are "managed". Developers can
+ * choose to either have their classes manually implement these interfaces or Hibernate can enhance their classes
+ * to implement these interfaces via built-time or run-time enhancement.
+ *
+ * @author Steve Ebersole
+ */
+public interface Managed {
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/ManagedComposite.java b/hibernate-core/src/main/java/org/hibernate/engine/ManagedComposite.java
new file mode 100644
index 0000000000..6ae9c65604
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/ManagedComposite.java
@@ -0,0 +1,32 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.engine;
+
+/**
+ * Specialized {@link Managed} contract for component/embeddable classes.
+ *
+ * @author Steve Ebersole
+ */
+public interface ManagedComposite extends Managed {
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/ManagedEntity.java b/hibernate-core/src/main/java/org/hibernate/engine/ManagedEntity.java
new file mode 100644
index 0000000000..28ecf15d92
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/ManagedEntity.java
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.engine;
+
+import org.hibernate.engine.spi.EntityEntry;
+
+/**
+ * Specialized {@link Managed} contract for entity classes.
+ *
+ * @author Steve Ebersole
+ */
+public interface ManagedEntity extends Managed {
+ /**
+ * Callback to get any associated EntityEntry.
+ *
+ * @return The EntityEntry associated with this entity instance.
+ *
+ * @see #hibernate_setEntityEntry
+ */
+ public EntityEntry hibernate_getEntityEntry();
+
+ /**
+ * Injects the EntityEntry associated with this entity instance. The EntityEntry represents state associated
+ * with the entity in regards to its association with a Hibernate Session.
+ *
+ * @param entityEntry The EntityEntry associated with this entity instance.
+ */
+ public void hibernate_setEntityEntry(EntityEntry entityEntry);
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryContext.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryContext.java
new file mode 100644
index 0000000000..4cb2999dd5
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryContext.java
@@ -0,0 +1,259 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2012, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.engine.internal;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.jboss.logging.Logger;
+
+import org.hibernate.LockMode;
+import org.hibernate.engine.ManagedEntity;
+import org.hibernate.engine.spi.EntityEntry;
+
+/**
+ * Defines a context for maintaining the relation between an entity associated with the Session ultimately owning this
+ * EntityEntryContext instance and that entity's corresponding EntityEntry. 2 approaches are supported:
+ *
+ * the entity->EntityEntry association is maintained in a Map within this class
+ *
+ *
+ * the EntityEntry is injected into the entity via it implementing the {@link org.hibernate.engine.ManagedEntity} contract,
+ * either directly or through bytecode enhancement.
+ *
+ *
+ *
+ * IMPL NOTE : This current implementation is not ideal in the {@link org.hibernate.engine.ManagedEntity} case. The problem is that
+ * the 'backingMap' is still the means to maintain ordering of the entries; but in the {@link org.hibernate.engine.ManagedEntity} case
+ * the use of a Map is overkill, and double here so because of the need for wrapping the map keys. But this is just
+ * a quick prototype.
+ *
+ * @author Steve Ebersole
+ */
+public class EntityEntryContext {
+ private static final Logger log = Logger.getLogger( EntityEntryContext.class );
+
+ private LinkedHashMap backingMap = new LinkedHashMap();
+
+ @SuppressWarnings( {"unchecked"})
+ private transient Map.Entry