From 0964b881f726d3a2bb1a207cf7105b4bc62027a8 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Wed, 5 Feb 2020 14:31:59 +0000 Subject: [PATCH] HHH-13851 Rework initialization of ProxyFactoryFactory, allow some code reuse from SPI --- .../proxy/pojo/ProxyFactoryHelper.java | 115 ++++++++++++++++++ .../tuple/entity/PojoEntityTuplizer.java | 80 ++---------- 2 files changed, 125 insertions(+), 70 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/proxy/pojo/ProxyFactoryHelper.java diff --git a/hibernate-core/src/main/java/org/hibernate/proxy/pojo/ProxyFactoryHelper.java b/hibernate-core/src/main/java/org/hibernate/proxy/pojo/ProxyFactoryHelper.java new file mode 100644 index 0000000000..af9a3d7e3b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/proxy/pojo/ProxyFactoryHelper.java @@ -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 . + */ +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 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 proxyInterfaces = new java.util.LinkedHashSet(); + 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 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; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java index 3d956718d3..491c5f7d5a 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java @@ -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.BytecodeProvider; @@ -29,14 +26,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; @@ -91,76 +86,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 + final String entityName = getEntityName(); + final Class mappedClass = persistentClass.getMappedClass(); + final Class proxyInterface = persistentClass.getProxyInterface(); - /* - * 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 proxyInterfaces = new java.util.LinkedHashSet(); + final Set proxyInterfaces = ProxyFactoryHelper.extractProxyInterfaces( persistentClass, entityName ); - Class mappedClass = persistentClass.getMappedClass(); - Class proxyInterface = persistentClass.getProxyInterface(); + ProxyFactoryHelper.validateProxyability( persistentClass ); - 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 ); - } - - if ( mappedClass.isInterface() ) { - proxyInterfaces.add( mappedClass ); - } - - Iterator 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, @@ -171,7 +111,7 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { ); } catch (HibernateException he) { - LOG.unableToCreateProxyFactory( getEntityName(), he ); + LOG.unableToCreateProxyFactory( entityName, he ); pf = null; } return pf;