/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.builder.generator;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.sf.cglib.core.ClassEmitter;
import net.sf.cglib.core.CodeEmitter;
import net.sf.cglib.core.EmitUtils;
import net.sf.cglib.core.MethodInfo;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.NoOp;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.asm.Type;
/**
* @author Nick - mailto:nbelaevski@exadel.com
* created 20.04.2007
*
*/
public class AbstractClassStubBuilder {
public static Object buildInterfaceStub(final Class<?> clazz, ClassLoader classLoader) throws InstantiationException, IllegalAccessException {
Enhancer enhancer = new Enhancer() {
public void generateClass(ClassVisitor v) throws Exception {
ClassEmitter ce = new ClassEmitter(v);
ce.begin_class(Constants.V1_5,
Constants.ACC_PUBLIC,
getClassName(),
null,
new Type[]{Type.getType(clazz)},
null);
EmitUtils.null_constructor(ce);
List methods = new ArrayList();
getMethods(Object.class, new Class[]{clazz}, methods);
for (Iterator iterator = methods.iterator(); iterator
.hasNext();) {
Method method = (Method) iterator.next();
if (Modifier.isAbstract(method.getModifiers())) {
MethodInfo methodInfo = ReflectUtils.getMethodInfo(method);
Signature signature = methodInfo.getSignature();
Type returnType = signature.getReturnType();
CodeEmitter e = ce.begin_method(method.getModifiers() & ~Modifier.ABSTRACT,
signature, methodInfo.getExceptionTypes(),
methodInfo.getAttribute());
e.zero_or_null(returnType);
e.return_value();
Type[] argumentTypes = methodInfo.getSignature().getArgumentTypes();
int size = 0;
if (argumentTypes != null) {
for (int i = 0; i < argumentTypes.length; i++) {
size += argumentTypes[i].getSize();
}
}
// 1 is for this
e.visitMaxs(returnType.getSize(), size + 1);
e.end_method();
}
}
ce.end_class();
}
};
enhancer.setCallbackType(NoOp.class);
enhancer.setInterfaces(new Class[]{clazz});
enhancer.setClassLoader(classLoader != null ?
classLoader : clazz.getClassLoader());
return enhancer.createClass().newInstance();
}
public static <T> T buildStub(final Class<T> clazz, MethodInterceptor interceptor,
ClassLoader classLoader) {
Class<T> instrumentedClass;
if ((Modifier.ABSTRACT & clazz.getModifiers()) != 0) {
Enhancer enhancer = new Enhancer() {
@Override
public void generateClass(ClassVisitor v) throws Exception {
ClassEmitter ce = new ClassEmitter(v);
ce.begin_class(Constants.V1_5,
Constants.ACC_PUBLIC,
getClassName(),
Type.getType(clazz),
null,
null);
EmitUtils.null_constructor(ce);
List methods = new ArrayList();
getMethods(clazz, null, methods);
for (Iterator iterator = methods.iterator(); iterator
.hasNext();) {
Method method = (Method) iterator.next();
if (Modifier.isAbstract(method.getModifiers())) {
MethodInfo methodInfo = ReflectUtils.getMethodInfo(method);
Signature signature = methodInfo.getSignature();
Type returnType = signature.getReturnType();
CodeEmitter e = ce.begin_method(method.getModifiers() & ~Modifier.ABSTRACT,
signature, methodInfo.getExceptionTypes(),
methodInfo.getAttribute());
e.zero_or_null(returnType);
e.return_value();
Type[] argumentTypes = methodInfo.getSignature().getArgumentTypes();
int size = 0;
if (argumentTypes != null) {
for (int i = 0; i < argumentTypes.length; i++) {
size += argumentTypes[i].getSize();
}
}
// 1 is for this
e.visitMaxs(returnType.getSize(), size + 1);
e.end_method();
}
}
ce.end_class();
}
};
enhancer.setSuperclass(clazz);
enhancer.setCallbackType(MethodInterceptor.class);
enhancer.setClassLoader(classLoader != null ?
classLoader : clazz.getClassLoader());
instrumentedClass = enhancer.createClass();
} else {
instrumentedClass = clazz;
}
Enhancer enhancer2 = new Enhancer();
enhancer2.setSuperclass(instrumentedClass);
enhancer2.setCallback(interceptor);
enhancer2.setClassLoader(instrumentedClass.getClassLoader());
return (T) enhancer2.create();
}
}