org.apache.dubbo.common.compiler.support.CtClassBuilder Maven / Gradle / Ivy
Show all versions of dubbo Show documentation
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.dubbo.common.compiler.support;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
/**
* CtClassBuilder is builder for CtClass
*
* contains all the information, including:
*
* class name, imported packages, super class name, implemented interfaces, constructors, fields, methods.
*/
public class CtClassBuilder {
private String className;
private String superClassName = "java.lang.Object";
private final List imports = new ArrayList<>();
private final Map fullNames = new HashMap<>();
private final List ifaces = new ArrayList<>();
private final List constructors = new ArrayList<>();
private final List fields = new ArrayList<>();
private final List methods = new ArrayList<>();
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getSuperClassName() {
return superClassName;
}
public void setSuperClassName(String superClassName) {
this.superClassName = getQualifiedClassName(superClassName);
}
public List getImports() {
return imports;
}
public void addImports(String pkg) {
int pi = pkg.lastIndexOf('.');
if (pi > 0) {
String pkgName = pkg.substring(0, pi);
this.imports.add(pkgName);
if (!pkg.endsWith(".*")) {
fullNames.put(pkg.substring(pi + 1), pkg);
}
}
}
public List getInterfaces() {
return ifaces;
}
public void addInterface(String iface) {
this.ifaces.add(getQualifiedClassName(iface));
}
public List getConstructors() {
return constructors;
}
public void addConstructor(String constructor) {
this.constructors.add(constructor);
}
public List getFields() {
return fields;
}
public void addField(String field) {
this.fields.add(field);
}
public List getMethods() {
return methods;
}
public void addMethod(String method) {
this.methods.add(method);
}
/**
* get full qualified class name
*
* @param className super class name, maybe qualified or not
*/
protected String getQualifiedClassName(String className) {
if (className.contains(".")) {
return className;
}
if (fullNames.containsKey(className)) {
return fullNames.get(className);
}
return ClassUtils.forName(imports.toArray(new String[0]), className).getName();
}
/**
* build CtClass object
*/
public CtClass build(ClassLoader classLoader) throws NotFoundException, CannotCompileException {
ClassPool pool = new ClassPool(true);
pool.appendClassPath(new LoaderClassPath(classLoader));
// create class
CtClass ctClass = pool.makeClass(className, pool.get(superClassName));
// add imported packages
imports.forEach(pool::importPackage);
// add implemented interfaces
for (String iface : ifaces) {
ctClass.addInterface(pool.get(iface));
}
// add constructors
for (String constructor : constructors) {
ctClass.addConstructor(CtNewConstructor.make(constructor, ctClass));
}
// add fields
for (String field : fields) {
ctClass.addField(CtField.make(field, ctClass));
}
// add methods
for (String method : methods) {
ctClass.addMethod(CtNewMethod.make(method, ctClass));
}
return ctClass;
}
}