package net.dubboclub.dubbogenerator;
import com.alibaba.dubbo.common.utils.StringUtils;
import javassist.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
/**
* Created by bieber on 2015/7/31.
*/
public class JavassistClassGenerator {
private List<String> mFields,mMethods, mInterfaces;
private static final AtomicLong CLASS_COUNTER = new AtomicLong(0);
private ClassPool classPool ;
private CtClass ctClass;
private String superClass;
private String className;
private static final ConcurrentHashMap<ClassLoader,ClassPool> LOADER_POOL = new ConcurrentHashMap<ClassLoader, ClassPool>();
private JavassistClassGenerator(ClassPool classPool){
this.classPool = classPool;
}
private static ClassLoader getCallerClassLoader(){
return JavassistClassGenerator.class.getClassLoader();
}
public static JavassistClassGenerator newInstance(){
return newInstance(getCallerClassLoader());
}
public static JavassistClassGenerator newInstance(ClassLoader classLoader){
return new JavassistClassGenerator(getClassPool(classLoader));
}
public void setClassName(String className){
this.className = className;
}
public void setSuperClass(String superClass){
this.superClass = superClass;
}
public void addInterface(String interfaceName){
if(mInterfaces ==null){
mInterfaces = new ArrayList<String>();
}
if(!StringUtils.isEmpty(interfaceName)){
mInterfaces.add(interfaceName);
}
}
public void addField(String fieldCode){
if(mFields==null){
mFields = new ArrayList<String>();
}
if(!StringUtils.isEmpty(fieldCode)){
mFields.add(fieldCode);
}
}
public void addMethod(String methodCode){
if(mMethods==null){
mMethods = new ArrayList<String>();
}
if(!StringUtils.isEmpty(methodCode)){
mMethods.add(methodCode);
}
}
public Class<?> toClass(){
if(ctClass!=null){
ctClass.detach();
}
try {
long id = CLASS_COUNTER.getAndIncrement();
if(StringUtils.isEmpty(className)){
className=(superClass==null?JavassistClassGenerator.class.getSimpleName():superClass+"$jcg")+id;
}
CtClass ctcs = superClass == null ? null : classPool.get(superClass);
ctClass = classPool.makeClass(className);
if(ctcs!=null){
ctClass.setSuperclass(ctcs);
}
if(mInterfaces !=null){
for(String mInterface:mInterfaces){
ctClass.addInterface(classPool.get(mInterface));
}
}
if(mFields!=null){
for(String mField:mFields){
ctClass.addField(CtField.make(mField,ctClass));
}
}
if(mMethods!=null){
for(String mMethod:mMethods){
ctClass.addMethod(CtNewMethod.make(mMethod,ctClass));
}
}
ctClass.addConstructor(CtNewConstructor.defaultConstructor(ctClass));
return ctClass.toClass(getCallerClassLoader(),null);
}catch (RuntimeException e){
throw e;
}catch (NotFoundException e) {
throw new RuntimeException(e.getMessage(),e);
} catch (CannotCompileException e) {
throw new RuntimeException(e.getMessage(),e);
}finally {
release();
}
}
private void release(){
if(ctClass!=null)ctClass.detach();
if(mFields!=null)mFields.clear();
if(mMethods!=null)mMethods.clear();
}
public static ClassPool getClassPool(ClassLoader loader)
{
if( loader == null )
return ClassPool.getDefault();
ClassPool pool = LOADER_POOL.get(loader);
if( pool == null )
{
pool = new ClassPool(true);
pool.appendClassPath(new LoaderClassPath(loader));
LOADER_POOL.put(loader, pool);
}
return pool;
}
}