use of javassist.CtConstructor in project UniverseCore by EB-wilson.
the class Expr method where.
/**
* Returns the constructor or method containing the expression.
*/
public CtBehavior where() {
MethodInfo mi = thisMethod;
CtBehavior[] cb = thisClass.getDeclaredBehaviors();
for (int i = cb.length - 1; i >= 0; --i) if (cb[i].getMethodInfo2() == mi)
return cb[i];
CtConstructor init = thisClass.getClassInitializer();
if (init != null && init.getMethodInfo2() == mi)
return init;
/* getDeclaredBehaviors() returns a list of methods/constructors.
* Although the list is cached in a CtClass object, it might be
* recreated for some reason. Thus, the member name and the signature
* must be also checked.
*/
for (int i = cb.length - 1; i >= 0; --i) {
if (thisMethod.getName().equals(cb[i].getMethodInfo2().getName()) && thisMethod.getDescriptor().equals(cb[i].getMethodInfo2().getDescriptor())) {
return cb[i];
}
}
throw new RuntimeException("fatal: not found");
}
use of javassist.CtConstructor in project skywalking by apache.
the class OALRuntime method generateMetricsClass.
/**
* Generate metrics class, and inject it to classloader
*/
private Class generateMetricsClass(AnalysisResult metricsStmt) throws OALCompileException {
String className = metricsClassName(metricsStmt, false);
CtClass parentMetricsClass = null;
try {
parentMetricsClass = classPool.get(METRICS_FUNCTION_PACKAGE + metricsStmt.getMetricsClassName());
} catch (NotFoundException e) {
log.error("Can't find parent class for " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
CtClass metricsClass = classPool.makeClass(metricsClassName(metricsStmt, true), parentMetricsClass);
try {
metricsClass.addInterface(classPool.get(WITH_METADATA_INTERFACE));
} catch (NotFoundException e) {
log.error("Can't find WithMetadata interface for " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
ClassFile metricsClassClassFile = metricsClass.getClassFile();
ConstPool constPool = metricsClassClassFile.getConstPool();
/**
* Create empty construct
*/
try {
CtConstructor defaultConstructor = CtNewConstructor.make("public " + className + "() {}", metricsClass);
metricsClass.addConstructor(defaultConstructor);
} catch (CannotCompileException e) {
log.error("Can't add empty constructor in " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
/**
* Add fields with annotations.
*
* private ${sourceField.typeName} ${sourceField.fieldName};
*/
for (SourceColumn field : metricsStmt.getFieldsFromSource()) {
try {
CtField newField = CtField.make("private " + field.getType().getName() + " " + field.getFieldName() + ";", metricsClass);
metricsClass.addField(newField);
metricsClass.addMethod(CtNewMethod.getter(field.getFieldGetter(), newField));
metricsClass.addMethod(CtNewMethod.setter(field.getFieldSetter(), newField));
AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
/**
* Add @Column(columnName = "${sourceField.columnName}")
*/
Annotation columnAnnotation = new Annotation(Column.class.getName(), constPool);
columnAnnotation.addMemberValue("columnName", new StringMemberValue(field.getColumnName(), constPool));
if (field.getType().equals(String.class)) {
columnAnnotation.addMemberValue("length", new IntegerMemberValue(constPool, field.getLength()));
}
annotationsAttribute.addAnnotation(columnAnnotation);
newField.getFieldInfo().addAttribute(annotationsAttribute);
} catch (CannotCompileException e) {
log.error("Can't add field(including set/get) " + field.getFieldName() + " in " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
}
/**
* Generate methods
*/
for (String method : METRICS_CLASS_METHODS) {
StringWriter methodEntity = new StringWriter();
try {
configuration.getTemplate("metrics/" + method + ".ftl").process(metricsStmt, methodEntity);
metricsClass.addMethod(CtNewMethod.make(methodEntity.toString(), metricsClass));
} catch (Exception e) {
log.error("Can't generate method " + method + " for " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
}
/**
* Add following annotation to the metrics class
*
* at Stream(name = "${tableName}", scopeId = ${sourceScopeId}, builder = ${metricsName}Metrics.Builder.class, processor = MetricsStreamProcessor.class)
*/
AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
Annotation streamAnnotation = new Annotation(Stream.class.getName(), constPool);
streamAnnotation.addMemberValue("name", new StringMemberValue(metricsStmt.getTableName(), constPool));
streamAnnotation.addMemberValue("scopeId", new IntegerMemberValue(constPool, metricsStmt.getFrom().getSourceScopeId()));
streamAnnotation.addMemberValue("builder", new ClassMemberValue(metricsBuilderClassName(metricsStmt, true), constPool));
streamAnnotation.addMemberValue("processor", new ClassMemberValue(METRICS_STREAM_PROCESSOR, constPool));
annotationsAttribute.addAnnotation(streamAnnotation);
metricsClassClassFile.addAttribute(annotationsAttribute);
Class targetClass;
try {
if (SystemUtils.isJavaVersionAtMost(JavaVersion.JAVA_1_8)) {
targetClass = metricsClass.toClass(currentClassLoader, null);
} else {
targetClass = metricsClass.toClass(MetricClassPackageHolder.class);
}
} catch (CannotCompileException e) {
log.error("Can't compile/load " + className + ".", e);
throw new OALCompileException(e.getMessage(), e);
}
log.debug("Generate metrics class, " + metricsClass.getName());
writeGeneratedFile(metricsClass, metricsClass.getSimpleName(), "metrics");
return targetClass;
}
use of javassist.CtConstructor in project skywalking by apache.
the class MeterSystem method create.
/**
* Create streaming calculation of the given metrics name. This methods is synchronized due to heavy implementation
* including creating dynamic class. Don't use this in concurrency runtime.
*
* @param metricsName The name used as the storage eneity and in the query stage.
* @param functionName The function provided through {@link MeterFunction}.
* @throws IllegalArgumentException if the parameter can't match the expectation.
* @throws UnexpectedException if binary code manipulation fails or stream core failure.
*/
public synchronized <T> void create(String metricsName, String functionName, ScopeType type, Class<T> dataType) throws IllegalArgumentException {
/**
* Create a new meter class dynamically.
*/
final Class<? extends AcceptableValue> meterFunction = functionRegister.get(functionName);
if (meterFunction == null) {
throw new IllegalArgumentException("Function " + functionName + " can't be found.");
}
boolean foundDataType = false;
String acceptance = null;
for (final Type genericInterface : meterFunction.getGenericInterfaces()) {
if (genericInterface instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
if (parameterizedType.getRawType().getTypeName().equals(AcceptableValue.class.getName())) {
Type[] arguments = parameterizedType.getActualTypeArguments();
if (arguments[0].equals(dataType)) {
foundDataType = true;
} else {
acceptance = arguments[0].getTypeName();
}
}
if (foundDataType) {
break;
}
}
}
if (!foundDataType) {
throw new IllegalArgumentException("Function " + functionName + " requires <" + acceptance + "> in AcceptableValue" + " but using " + dataType.getName() + " in the creation");
}
final CtClass parentClass;
try {
parentClass = classPool.get(meterFunction.getCanonicalName());
if (!Metrics.class.isAssignableFrom(meterFunction)) {
throw new IllegalArgumentException("Function " + functionName + " doesn't inherit from Metrics.");
}
} catch (NotFoundException e) {
throw new IllegalArgumentException("Function " + functionName + " can't be found by javaassist.");
}
final String className = formatName(metricsName);
/**
* Check whether the metrics class is already defined or not
*/
try {
CtClass existingMetric = classPool.get(METER_CLASS_PACKAGE + className);
if (existingMetric.getSuperclass() != parentClass || type != meterPrototypes.get(metricsName).getScopeType()) {
throw new IllegalArgumentException(metricsName + " has been defined, but calculate function or/are scope type is/are different.");
}
log.info("Metric {} is already defined, so skip the metric creation.", metricsName);
return;
} catch (NotFoundException e) {
}
CtClass metricsClass = classPool.makeClass(METER_CLASS_PACKAGE + className, parentClass);
/**
* Create empty construct
*/
try {
CtConstructor defaultConstructor = CtNewConstructor.make("public " + className + "() {}", metricsClass);
metricsClass.addConstructor(defaultConstructor);
} catch (CannotCompileException e) {
log.error("Can't add empty constructor in " + className + ".", e);
throw new UnexpectedException(e.getMessage(), e);
}
/**
* Generate `AcceptableValue<T> createNew()` method.
*/
try {
metricsClass.addMethod(CtNewMethod.make("" + "public org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue createNew() {" + " org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue meterVar = new " + METER_CLASS_PACKAGE + className + "();" + " ((org.apache.skywalking.oap.server.core.analysis.meter.Meter)meterVar).initMeta(\"" + metricsName + "\", " + type.getScopeId() + ");" + " return meterVar;" + " }", metricsClass));
} catch (CannotCompileException e) {
log.error("Can't generate createNew method for " + className + ".", e);
throw new UnexpectedException(e.getMessage(), e);
}
Class targetClass;
try {
if (SystemUtils.isJavaVersionAtMost(JavaVersion.JAVA_1_8)) {
targetClass = metricsClass.toClass(MeterSystem.class.getClassLoader(), null);
} else {
targetClass = metricsClass.toClass(MeterClassPackageHolder.class);
}
AcceptableValue prototype = (AcceptableValue) targetClass.newInstance();
meterPrototypes.put(metricsName, new MeterDefinition(type, prototype, dataType));
log.debug("Generate metrics class, " + metricsClass.getName());
MetricsStreamProcessor.getInstance().create(manager, new StreamDefinition(metricsName, type.getScopeId(), prototype.builder(), MetricsStreamProcessor.class), targetClass);
} catch (CannotCompileException | IllegalAccessException | InstantiationException | StorageException e) {
log.error("Can't compile/load/init " + className + ".", e);
throw new UnexpectedException(e.getMessage(), e);
}
}
use of javassist.CtConstructor in project DRouter by didi.
the class InterceptorCollect method generate.
@Override
public void generate(File routerDir) throws Exception {
CtClass ctClass = pool.makeClass(getPackageName() + ".InterceptorLoader");
CtClass superClass = pool.get("com.didi.drouter.store.MetaLoader");
ctClass.setSuperclass(superClass);
StringBuilder builder = new StringBuilder();
builder.append("public void load(java.util.Map data) {\n");
for (CtClass interceptorCc : interceptorClass.values()) {
try {
if (isNonStaticInnerClass(interceptorCc)) {
throw new Exception("Annotation can not use non static inner class");
}
if (!checkSuper(interceptorCc, "com.didi.drouter.router.IRouterInterceptor")) {
throw new Exception("@Interceptor class does not implement IRouterInterceptor interface");
}
Interceptor interceptor = (Interceptor) interceptorCc.getAnnotation(Interceptor.class);
CtClass proxyCc = null;
CtConstructor constructor = interceptorCc.getDeclaredConstructor(null);
if (constructor != null) {
CtClass proxyInterface = pool.get("com.didi.drouter.store.IRouterProxy");
proxyCc = pool.makeClass(PROXY + interceptorCc.getName().replace(".", "_"));
proxyCc.addInterface(proxyInterface);
String method1 = String.format("public java.lang.Object newInstance(android.content.Context context) {" + "{ return new %s();} }", interceptorCc.getName());
generatorClass(routerDir, proxyCc, method1, METHOD2);
}
// class is the key
StringBuilder itemBuilder = new StringBuilder();
itemBuilder.append(" data.put(");
itemBuilder.append(interceptorCc.getName());
itemBuilder.append(".class");
itemBuilder.append(", com.didi.drouter.store.RouterMeta.build(");
itemBuilder.append("com.didi.drouter.store.RouterMeta.INTERCEPTOR)");
itemBuilder.append(".assembleInterceptor(");
itemBuilder.append(interceptorCc.getName());
itemBuilder.append(".class, ");
itemBuilder.append(proxyCc != null ? "new " + proxyCc.getName() + "()" : "null");
itemBuilder.append(",");
itemBuilder.append(interceptor.priority());
itemBuilder.append(",");
itemBuilder.append(interceptor.global());
itemBuilder.append(",");
itemBuilder.append(interceptor.cache());
itemBuilder.append("));\n");
String name = interceptor.name();
if (!TextUtil.isEmpty(name)) {
// name is the key
itemBuilder.append(" data.put(\"");
itemBuilder.append(name);
itemBuilder.append("\", com.didi.drouter.store.RouterMeta.build(");
itemBuilder.append("com.didi.drouter.store.RouterMeta.INTERCEPTOR)");
itemBuilder.append(".assembleInterceptor(");
itemBuilder.append(interceptorCc.getName());
itemBuilder.append(".class, ");
itemBuilder.append(proxyCc != null ? "new " + proxyCc.getName() + "()" : "null");
itemBuilder.append(",");
itemBuilder.append(interceptor.priority());
itemBuilder.append(",");
itemBuilder.append(interceptor.global());
itemBuilder.append(",");
itemBuilder.append(interceptor.cache());
itemBuilder.append("));\n");
String duplicate = StoreUtil.insertUri(name, interceptorCc);
if (duplicate != null) {
throw new Exception("\"name=" + name + "\" on " + interceptorCc.getName() + "\nhas duplication of name with class: " + duplicate);
}
}
items.add(itemBuilder.toString());
} catch (Exception e) {
e.printStackTrace();
throw new Exception("Class: === " + interceptorCc.getName() + " ===\nCause: " + e.getMessage());
}
}
Collections.sort(items);
for (String item : items) {
builder.append(item);
}
builder.append("}");
Logger.d("\nclass InterceptorLoader" + "\n" + builder.toString());
generatorClass(routerDir, ctClass, builder.toString());
}
use of javassist.CtConstructor in project DRouter by didi.
the class ServiceCollect method generate.
@Override
public void generate(File routerDir) throws Exception {
CtClass ctClass = pool.makeClass(getPackageName() + ".ServiceLoader");
CtClass superClass = pool.get("com.didi.drouter.store.MetaLoader");
ctClass.setSuperclass(superClass);
StringBuilder builder = new StringBuilder();
builder.append("public void load(java.util.Map data) {\n");
CtClass featureInterface = pool.get("com.didi.drouter.service.IFeatureMatcher");
for (CtClass serviceCc : serviceClass.values()) {
try {
if (isNonStaticInnerClass(serviceCc)) {
throw new Exception("Annotation can not use non static inner class");
}
Annotation annotation = getAnnotation(serviceCc, Service.class);
ArrayMemberValue functionValue = (ArrayMemberValue) annotation.getMemberValue("function");
String[] aliasValue = ((Service) serviceCc.getAnnotation(Service.class)).alias();
ArrayMemberValue featureValue = (ArrayMemberValue) annotation.getMemberValue("feature");
int priority = ((Service) serviceCc.getAnnotation(Service.class)).priority();
int cacheValue = ((Service) serviceCc.getAnnotation(Service.class)).cache();
boolean anyAbility = false;
List<CtClass> functionCcList = new ArrayList<>();
for (int i = 0; i < functionValue.getValue().length; i++) {
ClassMemberValue functionCmv = (ClassMemberValue) functionValue.getValue()[i];
if ("com.didi.drouter.service.AnyAbility".equals(functionCmv.getValue())) {
anyAbility = true;
} else {
CtClass functionCc = getCtClass(functionCmv.getValue());
functionCcList.add(functionCc);
String[] superClassNames;
if ("com.didi.drouter.service.ICallService".equals(functionCmv.getValue())) {
superClassNames = new String[11];
for (int j = 0; j < 10; j++) {
superClassNames[j] = "com.didi.drouter.service.ICallService" + j;
}
superClassNames[10] = "com.didi.drouter.service.ICallServiceN";
} else {
superClassNames = new String[] { functionCc.getName() };
}
// ICallService should use unique alias, for using alias to determine which service
if (functionCmv.getValue().startsWith("com.didi.drouter.service.ICallService")) {
if (i <= aliasValue.length - 1) {
String duplicate = StoreUtil.insertCallAlias(aliasValue[i], serviceCc);
if (duplicate != null) {
throw new Exception("ICallService can't use the same alias with" + duplicate);
}
}
}
if (!checkSuper(serviceCc, superClassNames)) {
throw new Exception("@Service with function does not match interface");
}
}
}
if (anyAbility) {
functionCcList.clear();
functionCcList.addAll(collectSuper(serviceCc));
if (aliasValue.length > 1) {
throw new Exception("only use one alias at most to match AnyAbility");
}
if (featureValue != null && featureValue.getValue().length > 1) {
throw new Exception("only use one feature at most to match AnyAbility");
}
}
// traverse all the function argument, one function corresponding one function->(impl,feature) data
for (int i = 0; i < functionCcList.size(); i++) {
CtClass functionCc = functionCcList.get(i);
String alias = "";
if (aliasValue.length == 1) {
alias = aliasValue[0];
} else if (i < aliasValue.length) {
// affirm no AnyAbility
alias = aliasValue[i];
}
// one feature generator one feature matcher class
CtClass featureCc = null;
CtClass featureMatchCc = null;
if (featureValue != null) {
if (featureValue.getValue().length == 1) {
ClassMemberValue featureCmv = (ClassMemberValue) featureValue.getValue()[0];
featureCc = pool.get(featureCmv.getValue());
} else if (i < featureValue.getValue().length) {
// affirm no AnyAbility
ClassMemberValue featureCmv = (ClassMemberValue) featureValue.getValue()[i];
featureCc = pool.get(featureCmv.getValue());
}
}
if (featureCc != null) {
// avoid class duplication
String featureMatcher = MATCH + serviceCc.getName().replace(".", "_") + "__" + featureCc.getSimpleName();
featureMatchCc = pool.getOrNull(featureMatcher);
if (featureMatchCc == null) {
featureMatchCc = pool.makeClass(featureMatcher);
featureMatchCc.addInterface(featureInterface);
StringBuilder featureBuilder = new StringBuilder();
featureBuilder.append("\npublic boolean match(Object obj) {");
featureBuilder.append("\n return obj instanceof ");
featureBuilder.append(featureCc.getName());
completeMatchMethod(serviceCc, featureCc, featureBuilder);
featureBuilder.append(";\n}");
// Logger.d(featureBuilder.toString());
generatorClass(routerDir, featureMatchCc, featureBuilder.toString());
}
}
CtClass methodProxyCc = null;
String constructorMethod = null;
String executeMethod = null;
try {
CtConstructor constructor = serviceCc.getDeclaredConstructor(null);
if (constructor != null) {
constructorMethod = String.format("public java.lang.Object newInstance(android.content.Context context) {" + "{ return new %s();} }", serviceCc.getName());
}
} catch (NotFoundException ignore) {
}
CtMethod[] ctMethods = serviceCc.getMethods();
if (ctMethods != null) {
StringBuilder allIfStr = new StringBuilder();
Set<String> methodNames = new HashSet<>();
for (CtMethod method : ctMethods) {
boolean add = methodNames.add(method.getName() + "_$$_" + method.getParameterTypes().length);
Remote remote = (Remote) method.getAnnotation(Remote.class);
if (remote != null) {
if (!add) {
throw new Exception(String.format("The method \"%s\" with @Remote " + "can't be same name and same parameter count", method.getName()));
}
CtClass returnCc = method.getReturnType();
checkPrimitiveType(method.getName(), returnCc);
CtClass[] paraTypeCts = method.getParameterTypes();
StringBuilder para = new StringBuilder();
if (paraTypeCts != null) {
// argument type
for (int j = 0; j < paraTypeCts.length; j++) {
checkPrimitiveType(method.getName(), paraTypeCts[j]);
para.append(String.format("(%s) (args[%s])", paraTypeCts[j].getName(), j));
if (j != paraTypeCts.length - 1) {
para.append(",");
}
}
}
// return type
if (!"void".equals(returnCc.getName())) {
allIfStr.append(String.format("if (\"%s\".equals(methodName)) { return ((%s)instance).%s(%s); }", method.getName() + "_$$_" + method.getParameterTypes().length, serviceCc.getName(), method.getName(), para));
} else {
allIfStr.append(String.format("if (\"%s\".equals(methodName)) { ((%s)instance).%s(%s); return null; }", method.getName() + "_$$_" + method.getParameterTypes().length, serviceCc.getName(), method.getName(), para));
}
}
}
executeMethod = String.format("public java.lang.Object execute(Object instance, String methodName, Object[] " + "args) {" + "%s" + "throw " + "new com.didi.drouter.store.IRouterProxy.RemoteMethodMatchException();" + "}", allIfStr);
}
if (constructorMethod != null || executeMethod != null) {
CtClass proxyInterface = pool.get("com.didi.drouter.store.IRouterProxy");
String path = PROXY + serviceCc.getName().replace(".", "_");
methodProxyCc = pool.getOrNull(path);
if (methodProxyCc == null) {
methodProxyCc = pool.makeClass(path);
methodProxyCc.addInterface(proxyInterface);
generatorClass(routerDir, methodProxyCc, constructorMethod == null ? METHOD1 : constructorMethod, executeMethod == null ? METHOD2 : executeMethod);
}
}
StringBuilder itemBuilder = new StringBuilder();
itemBuilder.append(" put(");
itemBuilder.append(functionCc.getName());
itemBuilder.append(".class, com.didi.drouter.store.RouterMeta.build(");
itemBuilder.append("com.didi.drouter.store.RouterMeta.SERVICE)");
itemBuilder.append(".assembleService(");
itemBuilder.append(serviceCc.getName());
itemBuilder.append(".class, ");
itemBuilder.append(methodProxyCc != null ? "new " + methodProxyCc.getName() + "()" : "null");
itemBuilder.append(", \"");
itemBuilder.append(alias);
itemBuilder.append("\",");
itemBuilder.append(featureMatchCc != null ? "new " + featureMatchCc.getName() + "()" : "null");
itemBuilder.append(",");
itemBuilder.append(priority);
itemBuilder.append(",");
itemBuilder.append(cacheValue);
itemBuilder.append(")");
itemBuilder.append(", data);\n");
items.add(itemBuilder.toString());
}
} catch (Exception e) {
e.printStackTrace();
throw new Exception("Class: === " + serviceCc.getName() + " ===\nCause: " + e.getMessage());
}
}
Collections.sort(items);
for (String item : items) {
builder.append(item);
}
builder.append("}");
Logger.d("\nclass ServiceLoader" + "\n" + builder.toString());
generatorClass(routerDir, ctClass, builder.toString());
}
Aggregations