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

org.perfectable.introspection.proxy.ProxyBuilder Maven / Gradle / Ivy

There is a newer version: 5.1.0
Show newest version
package org.perfectable.introspection.proxy;

import java.lang.reflect.Modifier;

import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.Immutable;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * Builder pattern for proxies.
 *
 * 

This class allows chained and intuitive creation of proxy instances. It uses {@link ProxyService} to actually * create proxies, and loads required service automatically. * * @see ProxyService * @param type of proxies built */ @Immutable public final class ProxyBuilder { private ProxyBuilder(ClassLoader classLoader, Class baseClass, ImmutableList> interfaces, ProxyService service) { this.classLoader = classLoader; this.baseClass = baseClass; this.interfaces = interfaces; this.service = service; } @SuppressWarnings("Immutable") private final ClassLoader classLoader; private final Class baseClass; private final ImmutableList> interfaces; private final ProxyService service; /** * Creates new builder for class that is actually a class (not an interface). * *

This class will be used as a superclass of a proxy class. The class must not be final or primitive. * *

This builder will use service that supports building proxies with superclasses. * * @param superclass class to be used as superclass for a proxy * @param type of proxy * @return new proxy builder with specified class */ public static ProxyBuilder forClass(Class superclass) { checkArgument(!superclass.isInterface()); checkArgument(!superclass.isPrimitive()); checkArgument(!Modifier.isFinal(superclass.getModifiers())); ClassLoader classLoader = superclass.getClassLoader(); ProxyService service = ProxyService.INSTANCES.get(ProxyService.Feature.SUPERCLASS); return new ProxyBuilder(classLoader, superclass, ImmutableList.of(), service); } /** * Creates new builder for interface. * *

This interface will be implemented by proxy class. Proxy class will not have any specific superclass, it will * probably be {@link Object}. * * @param baseInterface interface that will be implemented by proxy class * @param type of proxy * @return new proxy builder with specified interface */ public static ProxyBuilder forInterface(Class baseInterface) { checkArgument(baseInterface.isInterface()); ClassLoader classLoader = baseInterface.getClassLoader(); ProxyService service = ProxyService.INSTANCES.get(); return new ProxyBuilder<>(classLoader, Object.class, ImmutableList.of(baseInterface), service); } /** * Creates new builder for specified type. * *

Depending on if {@code resultClass} is an interface or not, this method will behave either as * {@link #forInterface} or {@link #forClass} * * @param resultClass base proxy type * @param type of proxy * @return new proxy builder with specified interface */ public static ProxyBuilder forType(Class resultClass) { if (resultClass.isInterface()) { return forInterface(resultClass); } return forClass(resultClass); } /** * Creates proxy builder that have additional interface added to the proxy class. * * @param additionalInterface added interface * @return new proxy builder with additional interface */ public ProxyBuilder withInterface(Class additionalInterface) { checkArgument(additionalInterface.isInterface()); checkArgument(classLoader.equals(additionalInterface.getClassLoader())); ImmutableList> newInterfaces = ImmutableList.>builder() .addAll(interfaces).add(additionalInterface).build(); return new ProxyBuilder<>(classLoader, baseClass, newInterfaces, service); } /** * Creates proxy builder that have proxy service replaced. * *

This method is optional, and needed only if specific service needs to be used. ProxyBuilder will normally * select suitable service. * * @param newService proxy service to use for creating services * @return new proxy builder with replaced service */ public ProxyBuilder usingService(ProxyService newService) { return new ProxyBuilder<>(classLoader, baseClass, interfaces, newService); } /** * Creates instance of configured proxy class. * * @param handler method that proxy will delegate its calls to * @return proxy instance */ public I instantiate(InvocationHandler> handler) { return service.instantiate(classLoader, baseClass, interfaces, handler); } }