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;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.EntityNameResolver;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
|
||||
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
|
||||
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.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.proxy.ProxyFactory;
|
||||
import org.hibernate.proxy.pojo.ProxyFactoryHelper;
|
||||
import org.hibernate.tuple.Instantiator;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
||||
|
@ -92,76 +87,21 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
|
|||
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
|
||||
// determine the id getter and setter methods from the proxy interface (if any)
|
||||
// determine all interfaces needed by the resulting proxy
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
Set<Class> proxyInterfaces = new java.util.LinkedHashSet<Class>();
|
||||
final String entityName = getEntityName();
|
||||
final Class mappedClass = persistentClass.getMappedClass();
|
||||
final Class proxyInterface = persistentClass.getProxyInterface();
|
||||
|
||||
Class mappedClass = persistentClass.getMappedClass();
|
||||
Class proxyInterface = persistentClass.getProxyInterface();
|
||||
final Set<Class> proxyInterfaces = ProxyFactoryHelper.extractProxyInterfaces( persistentClass, entityName );
|
||||
|
||||
if ( proxyInterface != null && !mappedClass.equals( proxyInterface ) ) {
|
||||
if ( !proxyInterface.isInterface() ) {
|
||||
throw new MappingException(
|
||||
"proxy must be either an interface, or the class itself: " + getEntityName()
|
||||
);
|
||||
}
|
||||
proxyInterfaces.add( proxyInterface );
|
||||
}
|
||||
ProxyFactoryHelper.validateProxyability( persistentClass );
|
||||
|
||||
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 );
|
||||
|
||||
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 );
|
||||
Method proxyGetIdentifierMethod = ProxyFactoryHelper.extractProxyGetIdentifierMethod( idGetter, proxyInterface );
|
||||
Method proxySetIdentifierMethod = ProxyFactoryHelper.extractProxySetIdentifierMethod( idSetter, proxyInterface );
|
||||
|
||||
ProxyFactory pf = buildProxyFactoryInternal( persistentClass, idGetter, idSetter );
|
||||
try {
|
||||
pf.postInstantiate(
|
||||
getEntityName(),
|
||||
entityName,
|
||||
mappedClass,
|
||||
proxyInterfaces,
|
||||
proxyGetIdentifierMethod,
|
||||
|
@ -172,7 +112,7 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
|
|||
);
|
||||
}
|
||||
catch (HibernateException he) {
|
||||
LOG.unableToCreateProxyFactory( getEntityName(), he );
|
||||
LOG.unableToCreateProxyFactory( entityName, he );
|
||||
pf = null;
|
||||
}
|
||||
return pf;
|
||||
|
|
Loading…
Reference in New Issue