Java tutorial
/* * 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.javassist; import java.io.Serializable; import java.lang.reflect.Method; import java.util.Locale; import java.util.Set; import javassist.util.proxy.MethodFilter; import javassist.util.proxy.Proxy; 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.type.CompositeType; import static org.hibernate.internal.CoreLogging.messageLogger; /** * A {@link ProxyFactory} implementation for producing Javassist-based proxies. * * @author Muga Nishizawa */ public class JavassistProxyFactory implements ProxyFactory, Serializable { private static final CoreMessageLogger LOG = messageLogger(JavassistProxyFactory.class); private static final MethodFilter EXCLUDE_FILTER = m -> { // skip finalize methods and Groovy getMetaClass return !(m.getParameterCount() == 0 && m.getName().equals("finalize") || (m.getName().equals("getMetaClass") && m.getReturnType().getName().equals("groovy.lang.MetaClass"))); }; private Class persistentClass; private String entityName; private Class[] interfaces; private Method getIdentifierMethod; private Method setIdentifierMethod; private CompositeType componentIdType; private boolean overridesEquals; private Class proxyClass; public JavassistProxyFactory() { } @Override public void postInstantiate(final String entityName, final Class persistentClass, final Set<Class> interfaces, final Method getIdentifierMethod, final 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 = buildJavassistProxyFactory().createClass(); } private Class[] toArray(Set<Class> interfaces) { if (interfaces == null) { return ArrayHelper.EMPTY_CLASS_ARRAY; } return interfaces.toArray(new Class[interfaces.size()]); } private javassist.util.proxy.ProxyFactory buildJavassistProxyFactory() { return buildJavassistProxyFactory(persistentClass, interfaces); } public static javassist.util.proxy.ProxyFactory buildJavassistProxyFactory(final Class persistentClass, final Class[] interfaces) { javassist.util.proxy.ProxyFactory factory = new javassist.util.proxy.ProxyFactory() { @Override protected ClassLoader getClassLoader() { return persistentClass.getClassLoader(); } }; factory.setSuperclass(interfaces.length == 1 ? persistentClass : null); factory.setInterfaces(interfaces); factory.setFilter(EXCLUDE_FILTER); return factory; } @Override public HibernateProxy getProxy(Serializable id, SharedSessionContractImplementor session) throws HibernateException { final JavassistLazyInitializer initializer = new JavassistLazyInitializer(entityName, persistentClass, interfaces, id, getIdentifierMethod, setIdentifierMethod, componentIdType, session, overridesEquals); try { final HibernateProxy proxy = (HibernateProxy) proxyClass.getConstructor().newInstance(); ((Proxy) proxy).setHandler(initializer); initializer.constructed(); return proxy; } catch (NoSuchMethodException e) { String logMessage = LOG.bytecodeEnhancementFailedBecauseOfDefaultConstructor(entityName); LOG.error(logMessage, e); throw new HibernateException(logMessage, e); } catch (Throwable t) { String logMessage = LOG.bytecodeEnhancementFailed(entityName); LOG.error(logMessage, t); throw new HibernateException(logMessage, t); } } public static HibernateProxy deserializeProxy(SerializableProxy serializableProxy) { final JavassistLazyInitializer initializer = new JavassistLazyInitializer(serializableProxy.getEntityName(), serializableProxy.getPersistentClass(), serializableProxy.getInterfaces(), serializableProxy.getId(), resolveIdGetterMethod(serializableProxy), resolveIdSetterMethod(serializableProxy), serializableProxy.getComponentIdType(), null, ReflectHelper.overridesEquals(serializableProxy.getPersistentClass())); final javassist.util.proxy.ProxyFactory factory = buildJavassistProxyFactory( serializableProxy.getPersistentClass(), serializableProxy.getInterfaces()); // note: interface is assumed to already contain HibernateProxy.class try { final Class proxyClass = factory.createClass(); final HibernateProxy proxy = (HibernateProxy) proxyClass.newInstance(); ((Proxy) proxy).setHandler(initializer); initializer.constructed(); 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())); } } }