Proxy.java
/*-
* #%L
* io.earcam.instrumental.proxy.concrete
* %%
* Copyright (C) 2018 earcam
* %%
* SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
*
* You <b>must</b> choose to accept, in full - any individual or combination of
* the following licenses:
* <ul>
* <li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
* <li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
* <li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
* <li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
* </ul>
* #L%
*/
package io.earcam.instrumental.proxy.concrete;
import java.lang.reflect.InvocationHandler;
import org.objenesis.ObjenesisStd;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.NoOp;
/**
* Using Objenesis to avoid cgib invoking parent constructors
*
* see http://objenesis.org
* see https://github.com/cglib/cglib
*
*/
public final class Proxy {
private static final ObjenesisStd OBJENESIS = new ObjenesisStd();
private Proxy()
{}
/**
* <p>
* createProxy.
* </p>
*
* @param type a {@link java.lang.Class} object.
* @param handler a {@link java.lang.reflect.InvocationHandler} object.
* @param <T> a T object.
* @return a T object.
*/
public static <T> T createProxy(Class<T> type, InvocationHandler handler)
{
T proxy = newInstanceOf(proxyClassFrom(type));
setCallbacks(proxy, handler);
return proxy;
}
private static <T> Class<? extends T> proxyClassFrom(Class<T> type)
{
try {
return createEnhancer(type).createClass();
} catch(IllegalArgumentException e) {
throw new IllegalArgumentException("Cannot create proxy for " + type.getName(), e);
}
}
private static <T> ConstructorIgnorantEnhancer<T> createEnhancer(Class<T> type)
{
ConstructorIgnorantEnhancer<T> enhancer = new ConstructorIgnorantEnhancer<>();
enhancer.setSuperclass(type);
enhancer.setCallbackType(net.sf.cglib.proxy.InvocationHandler.class);
SignedPackageRenamingPolicy.apply(enhancer, type);
return enhancer;
}
private static <T> T newInstanceOf(Class<T> type)
{
return OBJENESIS.newInstance(type);
}
private static <T> void setCallbacks(T proxy, InvocationHandler handler)
{
net.sf.cglib.proxy.InvocationHandler cglibHandler = handler::invoke;
((Factory) proxy).setCallbacks(new Callback[] { cglibHandler, NoOp.INSTANCE });
}
}