package org.testory.plumbing.im.wildcard; import static org.testory.common.Classes.tryWrap; import static org.testory.plumbing.PlumbingException.check; import java.lang.reflect.Array; import java.lang.reflect.Modifier; import java.util.List; import org.objenesis.ObjenesisStd; import net.sf.cglib.core.CodeGenerationException; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.Factory; import net.sf.cglib.proxy.NoOp; public class Tokenizer { private Tokenizer() {} public static Tokenizer tokenizer() { return new Tokenizer(); } public <T> T token(Class<T> type) { check(type != null); if (type.isArray()) { return (T) Array.newInstance(type.getComponentType(), 0); } else if (type.isPrimitive()) { return (T) new ObjenesisStd().newInstance(tryWrap(type)); } else if (!Modifier.isAbstract(type.getModifiers())) { return new ObjenesisStd().newInstance(type); } else { return newCglibProxy(type); } } private static <T> T newCglibProxy(Class<T> type) { Enhancer enhancer = new Enhancer() { /** includes all constructors */ protected void filterConstructors(Class sc, List constructors) {} }; enhancer.setClassLoader(Thread.currentThread().getContextClassLoader()); class CglibBugWorkaround {} if (type == Object.class) { enhancer.setSuperclass(CglibBugWorkaround.class); enhancer.setInterfaces(new Class[0]); } else if (type.isInterface()) { enhancer.setSuperclass(CglibBugWorkaround.class); enhancer.setInterfaces(new Class[] { type }); } else { enhancer.setSuperclass(type); enhancer.setInterfaces(new Class[0]); } enhancer.setCallbackTypes(new Class[] { NoOp.class }); Class<?> proxyClass; try { proxyClass = enhancer.createClass(); } catch (CodeGenerationException e) { throw new IllegalArgumentException(e); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(e); } Factory proxy = (Factory) new ObjenesisStd().newInstance(proxyClass); proxy.setCallback(0, NoOp.INSTANCE); return (T) proxy; } }