All Downloads are FREE. Search and download functionalities are using the official Maven repository.

one.edee.oss.proxycian.bytebuddy.AbstractByteBuddyDispatcherInvocationHandler Maven / Gradle / Ivy

package one.edee.oss.proxycian.bytebuddy;

import one.edee.oss.proxycian.AbstractDispatcherInvocationHandler;
import one.edee.oss.proxycian.MethodClassification;
import one.edee.oss.proxycian.trait.ProxyStateAccessor;
import one.edee.oss.proxycian.trait.StandardJavaMethods;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import static one.edee.oss.proxycian.bytebuddy.ByteBuddyProxyGenerator.INVOCATION_HANDLER_FIELD;

/**
 * Abstract implementation to allow different ByteBuddy approaches to be used based on JDK version.
 *
 * @author Jan Novotný ([email protected]), FG Forrest a.s. (c) 2023
 */
public abstract class AbstractByteBuddyDispatcherInvocationHandler> extends AbstractDispatcherInvocationHandler {
    protected static final Class[] EMPTY_CLASS_ARRAY = new Class[0];

    public AbstractByteBuddyDispatcherInvocationHandler(T proxyState, Collection> methodClassifications) {
        super(proxyState, methodClassifications);
    }

    public AbstractByteBuddyDispatcherInvocationHandler(T proxyState, MethodClassification... methodClassifications) {
        super(proxyState, methodClassifications);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void addImplementationSpecificInvokers(List> methodClassifications) {
        methodClassifications.add(StandardJavaMethods.cloneMethodInvoker(objectToClone -> {
            try {
                final Field field = objectToClone.getClass().getDeclaredField(INVOCATION_HANDLER_FIELD);
                field.setAccessible(true);
                final S originalDispatcher = (S) field.get(objectToClone);

                final T originalProxyState = (T) objectToClone.getProxyState();
                final Method cloneMethod = originalProxyState.getClass().getDeclaredMethod("clone");
                cloneMethod.setAccessible(true);
                final T clonedState = (T) cloneMethod.invoke(originalProxyState);

                final List> interfaces = new LinkedList<>();
                final Class superClass = objectToClone.getClass().getSuperclass();
                if (!Object.class.equals(superClass)) {
                    interfaces.add(superClass);
                }
                for (Class anInterface : objectToClone.getClass().getInterfaces()) {
                    if (!ProxyStateAccessor.class.equals(anInterface)) {
                        interfaces.add(anInterface);
                    }
                }
                return makeClone(originalDispatcher, clonedState, interfaces);
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException |
                     NoSuchFieldException e) {
                throw new CloneNotSupportedException("Cannot clone the proxy instance due to: " + e.getMessage());
            }
        }));
    }

    protected abstract ProxyStateAccessor makeClone(
            S originalDispatcher,
            T clonedState,
            List> interfaces
    );
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy