/**
* Copyright 2001-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package be.selckin.swu.pmodel;
import net.sf.cglib.core.CollectionUtils;
import net.sf.cglib.core.VisibilityPredicate;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
/**
* Some code based on and taken from EasyMock
*/
public class ProxyFactory {
private final Objenesis objenesis = new ObjenesisStd();
@SuppressWarnings("unchecked")
public <T> T createProxy(Class<T> type, InvocationHandler handler) {
MethodInterceptor interceptor = new ProxyMethodInterceptor(handler);
Enhancer enhancer = new Enhancer() {
@SuppressWarnings("unchecked")
@Override
protected void filterConstructors(Class sc, List constructors) {
CollectionUtils.filter(constructors, new VisibilityPredicate(sc, true));
}
};
enhancer.setUseCache(false);
enhancer.setSuperclass(type);
enhancer.setCallbackType(interceptor.getClass());
Class<?> mockClass = enhancer.createClass();
Enhancer.registerCallbacks(mockClass, null);
Enhancer.registerStaticCallbacks(mockClass, new Callback[]{interceptor});
Factory mock = (Factory) objenesis.newInstance(mockClass);
// cglib has code that normally gets called in the constructor, but we instantiated the class without calling the constructor,
// so call the cglib code this way.
mock.getCallback(0);
return (T) mock;
}
public static class ProxyMethodInterceptor implements MethodInterceptor, Serializable {
private final InvocationHandler handler;
public ProxyMethodInterceptor(InvocationHandler handler) {
this.handler = handler;
}
@SuppressWarnings("ProhibitedExceptionDeclared")
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
return handler.invoke(obj, method, args);
}
}
}