org.hibernate.proxy.pojo.javassist.JavassistProxyFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.hibernate.proxy.pojo.javassist.JavassistProxyFactory.java

Source

/*
 * 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()));
        }
    }
}