Package org.netbeans.gradle.project.others

Source Code of org.netbeans.gradle.project.others.PluginClassImplementation$MultiDelegator

package org.netbeans.gradle.project.others;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;
import org.jtrim.utils.ExceptionHelper;
import org.netbeans.gradle.model.util.CollectionUtils;

public final class PluginClassImplementation {
    private final ClassFinder type;
    private final InvocationHandler invocationHandler;
    private final AtomicReference<Object> instanceRef;

    public PluginClassImplementation(
            ClassFinder type,
            Object delegateInstance) {
        this(type, new SimpleDelegator(delegateInstance));
    }

    public PluginClassImplementation(
            ClassFinder type,
            Object delegateInstance,
            InvocationHandlerFactory exceptionalCases) {
        this(type, new MultiDelegator(exceptionalCases, new SimpleDelegator(delegateInstance)));
    }

    private PluginClassImplementation(
            ClassFinder type,
            InvocationHandler invocationHandler) {

        ExceptionHelper.checkNotNullArgument(type, "type");
        ExceptionHelper.checkNotNullArgument(invocationHandler, "invocationHandler");

        this.type = type;
        this.invocationHandler = invocationHandler;
        this.instanceRef = new AtomicReference<>(null);
    }

    public Object tryGetAsPluginClass() {
        Object result = instanceRef.get();
        if (result == null) {
            instanceRef.compareAndSet(null, tryCreateProxyInstance());
            result = instanceRef.get();
        }
        return result;
    }

    private Object tryCreateProxyInstance() {
        Class<?> pluginClass = type.tryGetClass();
        if (pluginClass == null) {
            return null;
        }

        ClassLoader classLoader = pluginClass.getClassLoader();

        return Proxy.newProxyInstance(classLoader,
                new Class<?>[]{pluginClass},
                invocationHandler);
    }

    private static final class MultiDelegator
    implements
            InvocationHandler {

        private final InvocationHandlerFactory[] factories;

        public MultiDelegator(InvocationHandlerFactory... factories) {
            this.factories = factories.clone();
            CollectionUtils.checkNoNullElements(Arrays.asList(this.factories), "factories");
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            for (InvocationHandlerFactory factory: factories) {
                InvocationHandler handler = factory.tryGetInvocationHandler(proxy, method, args);
                if (handler != null) {
                    return handler.invoke(proxy, method, args);
                }
            }
            throw new UnsupportedOperationException("No handler for method: " + method);
        }
    }

    private static final class SimpleDelegator
    implements
            InvocationHandler,
            InvocationHandlerFactory {

        private final Object delegate;

        public SimpleDelegator(Object delegate) {
            ExceptionHelper.checkNotNullArgument(delegate, "delegate");
            this.delegate = delegate;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Method delegateMethod
                    = delegate.getClass().getMethod(method.getName(), method.getParameterTypes());
            return delegateMethod.invoke(delegate, args);
        }

        @Override
        public InvocationHandler tryGetInvocationHandler(Object proxy, Method method, Object[] args) {
            return this;
        }
    }
}
TOP

Related Classes of org.netbeans.gradle.project.others.PluginClassImplementation$MultiDelegator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.