diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java index 15f9104534..d9fe8a10ef 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java @@ -26,6 +26,7 @@ public class BasicProxyFactoryImpl implements BasicProxyFactory { private static final String PROXY_NAMING_SUFFIX = Environment.useLegacyProxyClassnames() ? "HibernateBasicProxy$" : "HibernateBasicProxy"; private final Class proxyClass; + private final ProxyConfiguration.Interceptor interceptor; @SuppressWarnings("unchecked") public BasicProxyFactoryImpl(Class superClass, Class[] interfaces, ByteBuddyState bytebuddy) { @@ -47,12 +48,13 @@ public class BasicProxyFactoryImpl implements BasicProxyFactory { .make() .load( superClassOrMainInterface.getClassLoader(), ByteBuddyState.resolveClassLoadingStrategy( superClassOrMainInterface ) ) .getLoaded(); + this.interceptor = new PassThroughInterceptor( proxyClass.getName() ); } public Object getProxy() { try { final ProxyConfiguration proxy = (ProxyConfiguration) proxyClass.newInstance(); - proxy.$$_hibernate_set_interceptor( new PassThroughInterceptor( proxy, proxyClass.getName() ) ); + proxy.$$_hibernate_set_interceptor( this.interceptor ); return proxy; } catch (Throwable t) { diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/PassThroughInterceptor.java b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/PassThroughInterceptor.java index 7d45e2c6cd..09b108a148 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/PassThroughInterceptor.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/PassThroughInterceptor.java @@ -11,57 +11,58 @@ import java.util.HashMap; import org.hibernate.proxy.ProxyConfiguration; -import net.bytebuddy.implementation.bind.annotation.AllArguments; -import net.bytebuddy.implementation.bind.annotation.Origin; -import net.bytebuddy.implementation.bind.annotation.RuntimeType; -import net.bytebuddy.implementation.bind.annotation.This; - public class PassThroughInterceptor implements ProxyConfiguration.Interceptor { - private HashMap data = new HashMap(); - private final Object proxiedObject; + private HashMap data = new HashMap<>(); private final String proxiedClassName; - public PassThroughInterceptor(Object proxiedObject, String proxiedClassName) { - this.proxiedObject = proxiedObject; + public PassThroughInterceptor(String proxiedClassName) { this.proxiedClassName = proxiedClassName; } - @SuppressWarnings("unchecked") @Override public Object intercept(Object instance, Method method, Object[] arguments) throws Exception { final String name = method.getName(); - if ( "toString".equals( name ) ) { + + if ( "toString".equals( name ) && arguments.length == 0 ) { return proxiedClassName + "@" + System.identityHashCode( instance ); } - else if ( "equals".equals( name ) ) { - return proxiedObject == instance; + + if ( "equals".equals( name ) && arguments.length == 1 ) { + return instance == arguments[0]; } - else if ( "hashCode".equals( name ) ) { + + if ( "hashCode".equals( name ) && arguments.length == 0 ) { return System.identityHashCode( instance ); } - final boolean hasGetterSignature = method.getParameterCount() == 0 - && method.getReturnType() != null; - final boolean hasSetterSignature = method.getParameterCount() == 1 - && ( method.getReturnType() == null || method.getReturnType() == void.class ); - - if ( name.startsWith( "get" ) && hasGetterSignature ) { + if ( name.startsWith( "get" ) && hasGetterSignature( method ) ) { final String propName = name.substring( 3 ); return data.get( propName ); } - else if ( name.startsWith( "is" ) && hasGetterSignature ) { + + if ( name.startsWith( "is" ) && hasGetterSignature( method ) ) { final String propName = name.substring( 2 ); return data.get( propName ); } - else if ( name.startsWith( "set" ) && hasSetterSignature ) { + + if ( name.startsWith( "set" ) && hasSetterSignature( method ) ) { final String propName = name.substring( 3 ); data.put( propName, arguments[0] ); return null; } - else { - // todo : what else to do here? - return null; - } + + // todo : what else to do here? + return null; + } + + private boolean hasGetterSignature(Method method) { + return method.getParameterCount() == 0 + && method.getReturnType() != null; + } + + private boolean hasSetterSignature(Method method) { + return method.getParameterCount() == 1 + && ( method.getReturnType() == null || method.getReturnType() == void.class ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/proxy/bytebuddy/ByteBuddyBasicProxyFactoryTest.java b/hibernate-core/src/test/java/org/hibernate/test/proxy/bytebuddy/ByteBuddyBasicProxyFactoryTest.java new file mode 100644 index 0000000000..8caeac93d4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/proxy/bytebuddy/ByteBuddyBasicProxyFactoryTest.java @@ -0,0 +1,92 @@ +/* + * 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.test.proxy.bytebuddy; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.hibernate.bytecode.internal.bytebuddy.BasicProxyFactoryImpl; +import org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +@TestForIssue(jiraKey = "HHH-12786") +public class ByteBuddyBasicProxyFactoryTest { + + private static final BasicProxyFactoryImpl BASIC_PROXY_FACTORY = new BasicProxyFactoryImpl( Entity.class, new Class[0], new ByteBuddyState() ); + + @Test + public void testEqualsHashCode() { + Object entityProxy = BASIC_PROXY_FACTORY.getProxy(); + + assertTrue( entityProxy.equals( entityProxy ) ); + assertNotNull( entityProxy.hashCode() ); + + Object otherEntityProxy = BASIC_PROXY_FACTORY.getProxy(); + assertFalse( entityProxy.equals( otherEntityProxy ) ); + } + + @Test + public void testToString() { + Object entityProxy = BASIC_PROXY_FACTORY.getProxy(); + + assertTrue( entityProxy.toString().contains( "HibernateBasicProxy" ) ); + } + + @Test + public void testGetterSetter() { + Entity entityProxy = (Entity) BASIC_PROXY_FACTORY.getProxy(); + + entityProxy.setBool( true ); + assertTrue( entityProxy.isBool() ); + entityProxy.setBool( false ); + assertFalse( entityProxy.isBool() ); + + entityProxy.setString( "John Irving" ); + assertEquals( "John Irving", entityProxy.getString() ); + } + + @Test + public void testNonGetterSetterMethod() { + Entity entityProxy = (Entity) BASIC_PROXY_FACTORY.getProxy(); + + assertNull( entityProxy.otherMethod() ); + } + + public static class Entity { + + private String string; + + private boolean bool; + + public Entity() { + } + + public boolean isBool() { + return bool; + } + + public void setBool(boolean bool) { + this.bool = bool; + } + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } + + public String otherMethod() { + return "a string"; + } + } +}