All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyFactory Maven / Gradle / Ivy
/*
* 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.bytebuddy;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import net.bytebuddy.TypeCache;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.ProxyFactory;
import org.hibernate.proxy.ProxyConfiguration;
import org.hibernate.type.CompositeType;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.NamingStrategy;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.dynamic.scaffold.TypeValidation;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatchers;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.hibernate.internal.CoreLogging.messageLogger;
public class ByteBuddyProxyFactory implements ProxyFactory, Serializable {
private static final CoreMessageLogger LOG = messageLogger( ByteBuddyProxyFactory.class );
private static final TypeCache CACHE =
new TypeCache.WithInlineExpunction(TypeCache.Sort.SOFT);
private Class persistentClass;
private String entityName;
private Class[] interfaces;
private Method getIdentifierMethod;
private Method setIdentifierMethod;
private CompositeType componentIdType;
private boolean overridesEquals;
private Class proxyClass;
@Override
public void postInstantiate(
String entityName,
Class persistentClass,
Set interfaces,
Method getIdentifierMethod,
Method setIdentifierMethod,
CompositeType componentIdType) throws HibernateException {
this.entityName = entityName;
this.persistentClass = persistentClass;
this.interfaces = toArray( interfaces );
this.getIdentifierMethod = getIdentifierMethod;
this.setIdentifierMethod = setIdentifierMethod;
this.componentIdType = componentIdType;
this.overridesEquals = ReflectHelper.overridesEquals( persistentClass );
this.proxyClass = buildProxy( persistentClass, this.interfaces );
}
private Class[] toArray(Set interfaces) {
if ( interfaces == null ) {
return ArrayHelper.EMPTY_CLASS_ARRAY;
}
return interfaces.toArray( new Class[interfaces.size()] );
}
public static Class buildProxy(
final Class persistentClass,
final Class[] interfaces) {
Set> key = new HashSet>();
if ( interfaces.length == 1 ) {
key.add( persistentClass );
}
key.addAll( Arrays.>asList( interfaces ) );
return CACHE.findOrInsert(persistentClass.getClassLoader(), new TypeCache.SimpleKey(key), new Callable>() {
@Override
public Class call() throws Exception {
return new ByteBuddy()
.with(TypeValidation.DISABLED)
.with(new NamingStrategy.SuffixingRandom("HibernateProxy"))
.subclass(interfaces.length == 1 ? persistentClass : Object.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING)
.implement((Type[]) interfaces)
.method(ElementMatchers.isVirtual().and(ElementMatchers.not(ElementMatchers.isFinalizer())))
.intercept(MethodDelegation.to(ProxyConfiguration.InterceptorDispatcher.class))
.method(ElementMatchers.nameStartsWith("$$_hibernate_").and(ElementMatchers.isVirtual()))
.intercept(SuperMethodCall.INSTANCE)
.defineField(ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE)
.implement(ProxyConfiguration.class)
.intercept(FieldAccessor.ofField(ProxyConfiguration.INTERCEPTOR_FIELD_NAME).withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC))
.make()
.load(persistentClass.getClassLoader())
.getLoaded();
}
}, CACHE);
}
@Override
public HibernateProxy getProxy(
Serializable id,
SharedSessionContractImplementor session) throws HibernateException {
final ByteBuddyInterceptor interceptor = new ByteBuddyInterceptor(
entityName,
persistentClass,
interfaces,
id,
getIdentifierMethod,
setIdentifierMethod,
componentIdType,
session,
overridesEquals
);
try {
final HibernateProxy proxy = (HibernateProxy) proxyClass.newInstance();
( (ProxyConfiguration) proxy ).$$_hibernate_set_interceptor( interceptor );
return proxy;
}
catch (Throwable t) {
LOG.error( LOG.bytecodeEnhancementFailed( entityName ), t );
throw new HibernateException( LOG.bytecodeEnhancementFailed( entityName ), t );
}
}
public static HibernateProxy deserializeProxy(SerializableProxy serializableProxy) {
final ByteBuddyInterceptor interceptor = new ByteBuddyInterceptor(
serializableProxy.getEntityName(),
serializableProxy.getPersistentClass(),
serializableProxy.getInterfaces(),
serializableProxy.getId(),
resolveIdGetterMethod( serializableProxy ),
resolveIdSetterMethod( serializableProxy ),
serializableProxy.getComponentIdType(),
null,
ReflectHelper.overridesEquals( serializableProxy.getPersistentClass() )
);
// note: interface is assumed to already contain HibernateProxy.class
try {
final Class proxyClass = buildProxy(
serializableProxy.getPersistentClass(),
serializableProxy.getInterfaces()
);
final HibernateProxy proxy = (HibernateProxy) proxyClass.newInstance();
( (ProxyConfiguration) proxy ).$$_hibernate_set_interceptor( interceptor );
return proxy;
}
catch (Throwable t) {
final String message = LOG.bytecodeEnhancementFailed( serializableProxy.getEntityName() );
LOG.error( message, t );
throw new HibernateException( message, t );
}
}
@SuppressWarnings("unchecked")
private static Method resolveIdGetterMethod(SerializableProxy serializableProxy) {
if ( serializableProxy.getIdentifierGetterMethodName() == null ) {
return null;
}
try {
return serializableProxy.getIdentifierGetterMethodClass().getDeclaredMethod( serializableProxy.getIdentifierGetterMethodName() );
}
catch (NoSuchMethodException e) {
throw new HibernateException(
String.format(
Locale.ENGLISH,
"Unable to deserialize proxy [%s, %s]; could not locate id getter method [%s] on entity class [%s]",
serializableProxy.getEntityName(),
serializableProxy.getId(),
serializableProxy.getIdentifierGetterMethodName(),
serializableProxy.getIdentifierGetterMethodClass()
)
);
}
}
@SuppressWarnings("unchecked")
private static Method resolveIdSetterMethod(SerializableProxy serializableProxy) {
if ( serializableProxy.getIdentifierSetterMethodName() == null ) {
return null;
}
try {
return serializableProxy.getIdentifierSetterMethodClass().getDeclaredMethod(
serializableProxy.getIdentifierSetterMethodName(),
serializableProxy.getIdentifierSetterMethodParams()
);
}
catch (NoSuchMethodException e) {
throw new HibernateException(
String.format(
Locale.ENGLISH,
"Unable to deserialize proxy [%s, %s]; could not locate id setter method [%s] on entity class [%s]",
serializableProxy.getEntityName(),
serializableProxy.getId(),
serializableProxy.getIdentifierSetterMethodName(),
serializableProxy.getIdentifierSetterMethodClass()
)
);
}
}
}