org.perfectable.introspection.proxy.JdkProxyService Maven / Gradle / Ivy
package org.perfectable.introspection.proxy;
import org.perfectable.introspection.ObjectMethods;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.auto.service.AutoService;
import com.google.errorprone.annotations.Immutable;
import static java.util.Objects.requireNonNull;
// THIS IS NOT A PUBLIC API: class must be public because of ServiceLoader
@SuppressWarnings("javadoc")
@Immutable
@AutoService(ProxyService.class)
public final class JdkProxyService implements ProxyService {
private static final Set SUPPORTED_FEATURES = EnumSet.noneOf(Feature.class);
private static final Class>[] EMPTY_CLASS_ARRAY = new Class>[0];
@Override
public boolean supportsFeature(Feature feature) {
return SUPPORTED_FEATURES.contains(feature);
}
@Override
public I instantiate(ClassLoader classLoader, Class> baseClass, List extends Class>> interfaces,
InvocationHandler super MethodInvocation> handler)
throws UnsupportedFeatureException {
if (!baseClass.getName().equals(Object.class.getName())) {
throw new UnsupportedFeatureException("JDK proxy cannot be created with superclass other than Object");
}
java.lang.reflect.InvocationHandler adapterHandler = JdkInvocationHandlerAdapter.adapt(handler);
Class>[] interfacesArray = interfaces.toArray(EMPTY_CLASS_ARRAY);
try {
@SuppressWarnings("unchecked")
I instance = (I) Proxy.newProxyInstance(classLoader, interfacesArray, adapterHandler);
return instance;
}
catch (IllegalArgumentException e) {
throw new AssertionError("Proxy construction failed", e);
}
}
private static final class JdkInvocationHandlerAdapter implements java.lang.reflect.InvocationHandler {
private final InvocationHandler super MethodInvocation> handler;
static JdkInvocationHandlerAdapter adapt(InvocationHandler super MethodInvocation> handler) {
return new JdkInvocationHandlerAdapter<>(handler);
}
private JdkInvocationHandlerAdapter(InvocationHandler super MethodInvocation> handler) {
this.handler = handler;
}
@Nullable
@Override
public Object invoke(@Nullable Object proxy, Method method,
@Nullable Object[] args)
throws Throwable {
requireNonNull(method);
if (method.equals(ObjectMethods.FINALIZE)) {
return null; // ignore proxy finalization
}
@SuppressWarnings("unchecked")
T castedProxy = (T) proxy;
@SuppressWarnings("unchecked")
MethodInvocation invocation = MethodInvocation.intercepted(method, castedProxy, args);
return this.handler.handle(invocation);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy