HHH-13851 Rework initialization of ProxyFactoryFactory, allow some code reuse from SPI
(cherry picked from commit 0964b881f7
)
This commit is contained in:
parent
9fc4f5b8e7
commit
8d73884cbf
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.proxy.pojo;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.internal.CoreLogging;
|
||||||
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.mapping.Subclass;
|
||||||
|
import org.hibernate.property.access.spi.Getter;
|
||||||
|
import org.hibernate.property.access.spi.Setter;
|
||||||
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
|
import org.hibernate.tuple.entity.PojoEntityTuplizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Most of this code was originally an internal detail of {@link PojoEntityTuplizer},
|
||||||
|
* then extracted to make it easier for integrators to initialize a custom
|
||||||
|
* {@link org.hibernate.proxy.ProxyFactory}.
|
||||||
|
*/
|
||||||
|
public final class ProxyFactoryHelper {
|
||||||
|
|
||||||
|
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( ProxyFactoryHelper.class );
|
||||||
|
|
||||||
|
private ProxyFactoryHelper() {
|
||||||
|
//not meant to be instantiated
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<Class> extractProxyInterfaces(final PersistentClass persistentClass, final String entityName) {
|
||||||
|
/*
|
||||||
|
* We need to preserve the order of the interfaces they were put into the set, since javassist will choose the
|
||||||
|
* first one's class-loader to construct the proxy class with. This is also the reason why HibernateProxy.class
|
||||||
|
* should be the last one in the order (on JBossAS7 its class-loader will be org.hibernate module's class-
|
||||||
|
* loader, which will not see the classes inside deployed apps. See HHH-3078
|
||||||
|
*/
|
||||||
|
final Set<Class> proxyInterfaces = new java.util.LinkedHashSet<Class>();
|
||||||
|
final Class mappedClass = persistentClass.getMappedClass();
|
||||||
|
final Class proxyInterface = persistentClass.getProxyInterface();
|
||||||
|
|
||||||
|
if ( proxyInterface != null && !mappedClass.equals( proxyInterface ) ) {
|
||||||
|
if ( !proxyInterface.isInterface() ) {
|
||||||
|
throw new MappingException(
|
||||||
|
"proxy must be either an interface, or the class itself: " + entityName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
proxyInterfaces.add( proxyInterface );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mappedClass.isInterface() ) {
|
||||||
|
proxyInterfaces.add( mappedClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<Subclass> subclasses = persistentClass.getSubclassIterator();
|
||||||
|
while ( subclasses.hasNext() ) {
|
||||||
|
final Subclass subclass = subclasses.next();
|
||||||
|
final Class subclassProxy = subclass.getProxyInterface();
|
||||||
|
final Class subclassClass = subclass.getMappedClass();
|
||||||
|
if ( subclassProxy != null && !subclassClass.equals( subclassProxy ) ) {
|
||||||
|
if ( !subclassProxy.isInterface() ) {
|
||||||
|
throw new MappingException(
|
||||||
|
"proxy must be either an interface, or the class itself: " + subclass.getEntityName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
proxyInterfaces.add( subclassProxy );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyInterfaces.add( HibernateProxy.class );
|
||||||
|
return proxyInterfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validateProxyability(final PersistentClass persistentClass) {
|
||||||
|
Iterator properties = persistentClass.getPropertyIterator();
|
||||||
|
Class clazz = persistentClass.getMappedClass();
|
||||||
|
while ( properties.hasNext() ) {
|
||||||
|
Property property = (Property) properties.next();
|
||||||
|
Method method = property.getGetter( clazz ).getMethod();
|
||||||
|
if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
|
||||||
|
LOG.gettersOfLazyClassesCannotBeFinal( persistentClass.getEntityName(), property.getName() );
|
||||||
|
}
|
||||||
|
method = property.getSetter( clazz ).getMethod();
|
||||||
|
if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
|
||||||
|
LOG.settersOfLazyClassesCannotBeFinal( persistentClass.getEntityName(), property.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Method extractProxySetIdentifierMethod(final Setter idSetter, final Class proxyInterface) {
|
||||||
|
Method idSetterMethod = idSetter == null ? null : idSetter.getMethod();
|
||||||
|
|
||||||
|
Method proxySetIdentifierMethod = idSetterMethod == null || proxyInterface == null ?
|
||||||
|
null :
|
||||||
|
ReflectHelper.getMethod( proxyInterface, idSetterMethod );
|
||||||
|
return proxySetIdentifierMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Method extractProxyGetIdentifierMethod(final Getter idGetter, final Class proxyInterface) {
|
||||||
|
Method idGetterMethod = idGetter == null ? null : idGetter.getMethod();
|
||||||
|
|
||||||
|
Method proxyGetIdentifierMethod = idGetterMethod == null || proxyInterface == null ?
|
||||||
|
null :
|
||||||
|
ReflectHelper.getMethod( proxyInterface, idGetterMethod );
|
||||||
|
return proxyGetIdentifierMethod;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,15 +7,12 @@
|
||||||
package org.hibernate.tuple.entity;
|
package org.hibernate.tuple.entity;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.EntityNameResolver;
|
import org.hibernate.EntityNameResolver;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
|
||||||
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
|
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
|
||||||
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
|
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
|
||||||
import org.hibernate.bytecode.spi.ReflectionOptimizer;
|
import org.hibernate.bytecode.spi.ReflectionOptimizer;
|
||||||
|
@ -27,14 +24,12 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.Subclass;
|
|
||||||
import org.hibernate.property.access.spi.Getter;
|
import org.hibernate.property.access.spi.Getter;
|
||||||
import org.hibernate.property.access.spi.Setter;
|
import org.hibernate.property.access.spi.Setter;
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
|
||||||
import org.hibernate.proxy.ProxyFactory;
|
import org.hibernate.proxy.ProxyFactory;
|
||||||
|
import org.hibernate.proxy.pojo.ProxyFactoryHelper;
|
||||||
import org.hibernate.tuple.Instantiator;
|
import org.hibernate.tuple.Instantiator;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
|
|
||||||
|
@ -92,76 +87,21 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
|
||||||
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
|
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
|
||||||
// determine the id getter and setter methods from the proxy interface (if any)
|
// determine the id getter and setter methods from the proxy interface (if any)
|
||||||
// determine all interfaces needed by the resulting proxy
|
// determine all interfaces needed by the resulting proxy
|
||||||
|
final String entityName = getEntityName();
|
||||||
/*
|
final Class mappedClass = persistentClass.getMappedClass();
|
||||||
* We need to preserve the order of the interfaces they were put into the set, since javassist will choose the
|
final Class proxyInterface = persistentClass.getProxyInterface();
|
||||||
* first one's class-loader to construct the proxy class with. This is also the reason why HibernateProxy.class
|
|
||||||
* should be the last one in the order (on JBossAS7 its class-loader will be org.hibernate module's class-
|
|
||||||
* loader, which will not see the classes inside deployed apps. See HHH-3078
|
|
||||||
*/
|
|
||||||
Set<Class> proxyInterfaces = new java.util.LinkedHashSet<Class>();
|
|
||||||
|
|
||||||
Class mappedClass = persistentClass.getMappedClass();
|
final Set<Class> proxyInterfaces = ProxyFactoryHelper.extractProxyInterfaces( persistentClass, entityName );
|
||||||
Class proxyInterface = persistentClass.getProxyInterface();
|
|
||||||
|
|
||||||
if ( proxyInterface != null && !mappedClass.equals( proxyInterface ) ) {
|
ProxyFactoryHelper.validateProxyability( persistentClass );
|
||||||
if ( !proxyInterface.isInterface() ) {
|
|
||||||
throw new MappingException(
|
|
||||||
"proxy must be either an interface, or the class itself: " + getEntityName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
proxyInterfaces.add( proxyInterface );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( mappedClass.isInterface() ) {
|
Method proxyGetIdentifierMethod = ProxyFactoryHelper.extractProxyGetIdentifierMethod( idGetter, proxyInterface );
|
||||||
proxyInterfaces.add( mappedClass );
|
Method proxySetIdentifierMethod = ProxyFactoryHelper.extractProxySetIdentifierMethod( idSetter, proxyInterface );
|
||||||
}
|
|
||||||
|
|
||||||
Iterator<Subclass> subclasses = persistentClass.getSubclassIterator();
|
|
||||||
while ( subclasses.hasNext() ) {
|
|
||||||
final Subclass subclass = subclasses.next();
|
|
||||||
final Class subclassProxy = subclass.getProxyInterface();
|
|
||||||
final Class subclassClass = subclass.getMappedClass();
|
|
||||||
if ( subclassProxy != null && !subclassClass.equals( subclassProxy ) ) {
|
|
||||||
if ( !subclassProxy.isInterface() ) {
|
|
||||||
throw new MappingException(
|
|
||||||
"proxy must be either an interface, or the class itself: " + subclass.getEntityName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
proxyInterfaces.add( subclassProxy );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proxyInterfaces.add( HibernateProxy.class );
|
|
||||||
|
|
||||||
Iterator properties = persistentClass.getPropertyIterator();
|
|
||||||
Class clazz = persistentClass.getMappedClass();
|
|
||||||
while ( properties.hasNext() ) {
|
|
||||||
Property property = (Property) properties.next();
|
|
||||||
Method method = property.getGetter( clazz ).getMethod();
|
|
||||||
if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
|
|
||||||
LOG.gettersOfLazyClassesCannotBeFinal( persistentClass.getEntityName(), property.getName() );
|
|
||||||
}
|
|
||||||
method = property.getSetter( clazz ).getMethod();
|
|
||||||
if ( method != null && Modifier.isFinal( method.getModifiers() ) ) {
|
|
||||||
LOG.settersOfLazyClassesCannotBeFinal( persistentClass.getEntityName(), property.getName() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Method idGetterMethod = idGetter == null ? null : idGetter.getMethod();
|
|
||||||
Method idSetterMethod = idSetter == null ? null : idSetter.getMethod();
|
|
||||||
|
|
||||||
Method proxyGetIdentifierMethod = idGetterMethod == null || proxyInterface == null ?
|
|
||||||
null :
|
|
||||||
ReflectHelper.getMethod( proxyInterface, idGetterMethod );
|
|
||||||
Method proxySetIdentifierMethod = idSetterMethod == null || proxyInterface == null ?
|
|
||||||
null :
|
|
||||||
ReflectHelper.getMethod( proxyInterface, idSetterMethod );
|
|
||||||
|
|
||||||
ProxyFactory pf = buildProxyFactoryInternal( persistentClass, idGetter, idSetter );
|
ProxyFactory pf = buildProxyFactoryInternal( persistentClass, idGetter, idSetter );
|
||||||
try {
|
try {
|
||||||
pf.postInstantiate(
|
pf.postInstantiate(
|
||||||
getEntityName(),
|
entityName,
|
||||||
mappedClass,
|
mappedClass,
|
||||||
proxyInterfaces,
|
proxyInterfaces,
|
||||||
proxyGetIdentifierMethod,
|
proxyGetIdentifierMethod,
|
||||||
|
@ -172,7 +112,7 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (HibernateException he) {
|
catch (HibernateException he) {
|
||||||
LOG.unableToCreateProxyFactory( getEntityName(), he );
|
LOG.unableToCreateProxyFactory( entityName, he );
|
||||||
pf = null;
|
pf = null;
|
||||||
}
|
}
|
||||||
return pf;
|
return pf;
|
||||||
|
|
Loading…
Reference in New Issue