use of javassist.CtConstructor in project JavaAgentTools by ethushiroha.
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 JavaAgentTools by ethushiroha.
the class Javac method compileMethod.
private CtBehavior compileMethod(Parser p, MethodDecl md) throws CompileError {
int mod = MemberResolver.getModifiers(md.getModifiers());
CtClass[] plist = gen.makeParamList(md);
CtClass[] tlist = gen.makeThrowsList(md);
recordParams(plist, Modifier.isStatic(mod));
md = p.parseMethod2(stable, md);
try {
if (md.isConstructor()) {
CtConstructor cons = new CtConstructor(plist, gen.getThisClass());
cons.setModifiers(mod);
md.accept(gen);
cons.getMethodInfo().setCodeAttribute(bytecode.toCodeAttribute());
cons.setExceptionTypes(tlist);
return cons;
} else {
Declarator r = md.getReturn();
CtClass rtype = gen.resolver.lookupClass(r);
recordReturnType(rtype, false);
CtMethod method = new CtMethod(rtype, r.getVariable().get(), plist, gen.getThisClass());
method.setModifiers(mod);
gen.setThisMethod(method);
md.accept(gen);
if (md.getBody() != null)
method.getMethodInfo().setCodeAttribute(bytecode.toCodeAttribute());
else
method.setModifiers(mod | Modifier.ABSTRACT);
method.setExceptionTypes(tlist);
return method;
}
} catch (NotFoundException e) {
throw new CompileError(e.toString());
}
}
use of javassist.CtConstructor in project JavaAgentTools by ethushiroha.
the class Javac method compileBody.
/**
* Compiles a method (or constructor) body.
*
* @src a single statement or a block.
* If null, this method produces a body returning zero or null.
*/
public Bytecode compileBody(CtBehavior method, String src) throws CompileError {
try {
int mod = method.getModifiers();
recordParams(method.getParameterTypes(), Modifier.isStatic(mod));
CtClass rtype;
if (method instanceof CtMethod) {
gen.setThisMethod((CtMethod) method);
rtype = ((CtMethod) method).getReturnType();
} else
rtype = CtClass.voidType;
recordReturnType(rtype, false);
boolean isVoid = rtype == CtClass.voidType;
if (src == null)
makeDefaultBody(bytecode, rtype);
else {
Parser p = new Parser(new Lex(src));
SymbolTable stb = new SymbolTable(stable);
Stmnt s = p.parseStatement(stb);
if (p.hasMore())
throw new CompileError("the method/constructor body must be surrounded by {}");
boolean callSuper = false;
if (method instanceof CtConstructor)
callSuper = !((CtConstructor) method).isClassInitializer();
gen.atMethodBody(s, callSuper, isVoid);
}
return bytecode;
} catch (NotFoundException e) {
throw new CompileError(e.toString());
}
}
use of javassist.CtConstructor in project dexcount-gradle-plugin by KeepSafe.
the class SourceFiles method extractMethodRefs.
private static Stream<MethodRef> extractMethodRefs(CtClass clazz) {
String declaringClass = "L" + clazz.getName().replace(".", "/") + ";";
// Unfortunately, it's necessary to parse the types from the strings manually.
// We can't use the proper API because this requires all classes that are used
// in parameters and return types to be loaded in the classpath. However,
// that's not the case when we analyze a single jar file.
List<MethodRef> results = new ArrayList<>();
if (clazz.getClassInitializer() != null) {
results.add(new MethodRef(declaringClass, new String[0], "V", "<clinit>"));
}
for (CtConstructor ctor : clazz.getDeclaredConstructors()) {
String[] params = parseBehaviorParameters(ctor);
results.add(new MethodRef(declaringClass, params, "V", "<init>"));
}
for (CtMethod method : clazz.getDeclaredMethods()) {
String[] params = parseBehaviorParameters(method);
String returnType = parseMethodReturnType(method);
results.add(new MethodRef(declaringClass, params, returnType, method.getName()));
}
return results.stream();
}
use of javassist.CtConstructor in project BroadleafCommerce by BroadleafCommerce.
the class DirectCopyClassTransformer method transform.
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
// Lambdas and anonymous methods in Java 8 do not have a class name defined and so no transformation should be done
if (className == null) {
return null;
}
// Be careful with Apache library usage in this class (e.g. ArrayUtils). Usage will likely cause a ClassCircularityError
// under JRebel. Favor not including outside libraries and unnecessary classes.
CtClass clazz = null;
try {
boolean mySkipOverlaps = skipOverlaps;
boolean myRenameMethodOverlaps = renameMethodOverlaps;
String convertedClassName = className.replace('/', '.');
ClassPool classPool = null;
String xformKey = convertedClassName;
String[] xformVals = null;
Boolean[] xformSkipOverlaps = null;
Boolean[] xformRenameMethodOverlaps = null;
if (!xformTemplates.isEmpty()) {
if (xformTemplates.containsKey(xformKey)) {
xformVals = xformTemplates.get(xformKey).split(",");
classPool = ClassPool.getDefault();
clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false);
}
} else {
if (annotationTransformedClasses.contains(convertedClassName)) {
logger.warn(convertedClassName + " has already been transformed by a previous instance of DirectCopyTransfomer. " + "Skipping this annotation based transformation. Generally, annotation-based transformation is handled " + "by bean id blAnnotationDirectCopyClassTransformer with template tokens being added to " + "blDirectCopyTransformTokenMap via EarlyStageMergeBeanPostProcessor.");
}
boolean isValidPattern = true;
List<DirectCopyIgnorePattern> matchedPatterns = new ArrayList<DirectCopyIgnorePattern>();
for (DirectCopyIgnorePattern pattern : ignorePatterns) {
boolean isPatternMatch = false;
for (String patternString : pattern.getPatterns()) {
isPatternMatch = convertedClassName.matches(patternString);
if (isPatternMatch) {
break;
}
}
if (isPatternMatch) {
matchedPatterns.add(pattern);
}
isValidPattern = !(isPatternMatch && pattern.getTemplateTokenPatterns() == null);
if (!isValidPattern) {
return null;
}
}
if (isValidPattern) {
classPool = ClassPool.getDefault();
clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false);
List<?> attributes = clazz.getClassFile().getAttributes();
Iterator<?> itr = attributes.iterator();
List<String> templates = new ArrayList<String>();
List<Boolean> skips = new ArrayList<Boolean>();
List<Boolean> renames = new ArrayList<Boolean>();
check: {
while (itr.hasNext()) {
Object object = itr.next();
if (AnnotationsAttribute.class.isAssignableFrom(object.getClass())) {
AnnotationsAttribute attr = (AnnotationsAttribute) object;
Annotation[] items = attr.getAnnotations();
for (Annotation annotation : items) {
String typeName = annotation.getTypeName();
if (typeName.equals(DirectCopyTransform.class.getName())) {
ArrayMemberValue arrayMember = (ArrayMemberValue) annotation.getMemberValue("value");
for (MemberValue arrayMemberValue : arrayMember.getValue()) {
AnnotationMemberValue member = (AnnotationMemberValue) arrayMemberValue;
Annotation memberAnnot = member.getValue();
ArrayMemberValue annot = (ArrayMemberValue) memberAnnot.getMemberValue("templateTokens");
for (MemberValue memberValue : annot.getValue()) {
String val = ((StringMemberValue) memberValue).getValue();
if (val != null && templateTokens.containsKey(val)) {
templateCheck: {
for (DirectCopyIgnorePattern matchedPattern : matchedPatterns) {
for (String ignoreToken : matchedPattern.getTemplateTokenPatterns()) {
if (val.matches(ignoreToken)) {
break templateCheck;
}
}
}
String[] templateVals = templateTokens.get(val).split(",");
templates.addAll(Arrays.asList(templateVals));
}
}
}
BooleanMemberValue skipAnnot = (BooleanMemberValue) memberAnnot.getMemberValue("skipOverlaps");
if (skipAnnot != null) {
skips.add(skipAnnot.getValue());
} else {
skips.add(mySkipOverlaps);
}
BooleanMemberValue renameAnnot = (BooleanMemberValue) memberAnnot.getMemberValue("renameMethodOverlaps");
if (renameAnnot != null) {
renames.add(renameAnnot.getValue());
} else {
renames.add(myRenameMethodOverlaps);
}
}
xformVals = templates.toArray(new String[templates.size()]);
xformSkipOverlaps = skips.toArray(new Boolean[skips.size()]);
xformRenameMethodOverlaps = renames.toArray(new Boolean[renames.size()]);
break check;
}
}
}
}
}
}
}
if (xformVals != null && xformVals.length > 0) {
logger.debug(String.format("[%s] - Transform - Copying into [%s] from [%s]", LifeCycleEvent.END, xformKey, StringUtils.join(xformVals, ",")));
// Load the destination class and defrost it so it is eligible for modifications
clazz.defrost();
int index = 0;
for (String xformVal : xformVals) {
// Load the source class
String trimmed = xformVal.trim();
classPool.appendClassPath(new LoaderClassPath(Class.forName(trimmed).getClassLoader()));
CtClass template = classPool.get(trimmed);
// Add in extra interfaces
CtClass[] interfacesToCopy = template.getInterfaces();
for (CtClass i : interfacesToCopy) {
checkInterfaces: {
CtClass[] myInterfaces = clazz.getInterfaces();
for (CtClass myInterface : myInterfaces) {
if (myInterface.getName().equals(i.getName())) {
if (xformSkipOverlaps != null && xformSkipOverlaps[index]) {
break checkInterfaces;
} else {
throw new RuntimeException("Duplicate interface detected " + myInterface.getName());
}
}
}
logger.debug(String.format("Adding interface [%s]", i.getName()));
clazz.addInterface(i);
}
}
// copy over any EntityListeners
ClassFile classFile = clazz.getClassFile();
ClassFile templateFile = template.getClassFile();
ConstPool constantPool = classFile.getConstPool();
buildClassLevelAnnotations(classFile, templateFile, constantPool);
// Copy over all declared fields from the template class
// Note that we do not copy over fields with the @NonCopiedField annotation
CtField[] fieldsToCopy = template.getDeclaredFields();
for (CtField field : fieldsToCopy) {
if (field.hasAnnotation(NonCopied.class)) {
logger.debug(String.format("Not adding field [%s]", field.getName()));
} else {
try {
CtField ctField = clazz.getDeclaredField(field.getName());
String originalSignature = ctField.getSignature();
String mySignature = field.getSignature();
if (!originalSignature.equals(mySignature)) {
throw new IllegalArgumentException("Field with name (" + field.getName() + ") and signature " + "(" + field.getSignature() + ") is targeted for weaving into (" + clazz.getName() + "). " + "An incompatible field of the same name and signature of (" + ctField.getSignature() + ") " + "already exists. The field in the target class should be updated to a different name, " + "or made to have a matching type.");
}
if (xformSkipOverlaps != null && xformSkipOverlaps[index]) {
logger.debug(String.format("Skipping overlapped field [%s]", field.getName()));
continue;
}
} catch (NotFoundException e) {
// do nothing -- field does not exist
}
logger.debug(String.format("Adding field [%s]", field.getName()));
CtField copiedField = new CtField(field, clazz);
boolean defaultConstructorFound = false;
String implClass = getImplementationType(field.getType().getName());
// if there is one that takes zero parameters
try {
CtConstructor[] implConstructors = classPool.get(implClass).getConstructors();
if (implConstructors != null) {
for (CtConstructor cons : implConstructors) {
if (cons.getParameterTypes().length == 0) {
defaultConstructorFound = true;
break;
}
}
}
} catch (NotFoundException e) {
// Do nothing -- if we don't find this implementation, it's probably because it's
// an array. In this case, we will not initialize the field.
}
if (defaultConstructorFound) {
clazz.addField(copiedField, "new " + implClass + "()");
} else {
clazz.addField(copiedField);
}
}
}
// Copy over all declared methods from the template class
CtMethod[] methodsToCopy = template.getDeclaredMethods();
for (CtMethod method : methodsToCopy) {
if (method.hasAnnotation(NonCopied.class)) {
logger.debug(String.format("Not adding method [%s]", method.getName()));
} else {
try {
CtClass[] paramTypes = method.getParameterTypes();
CtMethod originalMethod = clazz.getDeclaredMethod(method.getName(), paramTypes);
if (xformSkipOverlaps != null && xformSkipOverlaps[index]) {
logger.debug(String.format("Skipping overlapped method [%s]", methodDescription(originalMethod)));
continue;
}
if (transformedMethods.contains(methodDescription(originalMethod))) {
throw new RuntimeException("Method already replaced " + methodDescription(originalMethod));
} else {
logger.debug(String.format("Marking as replaced [%s]", methodDescription(originalMethod)));
transformedMethods.add(methodDescription(originalMethod));
}
logger.debug(String.format("Removing method [%s]", method.getName()));
if (xformRenameMethodOverlaps != null && xformRenameMethodOverlaps[index]) {
originalMethod.setName(renameMethodPrefix + method.getName());
} else {
clazz.removeMethod(originalMethod);
}
} catch (NotFoundException e) {
// Do nothing -- we don't need to remove a method because it doesn't exist
}
logger.debug(String.format("Adding method [%s]", method.getName()));
CtMethod copiedMethod = new CtMethod(method, clazz, null);
clazz.addMethod(copiedMethod);
}
}
index++;
}
if (xformTemplates.isEmpty()) {
annotationTransformedClasses.add(convertedClassName);
}
logger.debug(String.format("[%s] - Transform - Copying into [%s] from [%s]", LifeCycleEvent.END, xformKey, StringUtils.join(xformVals, ",")));
return clazz.toBytecode();
}
} catch (ClassCircularityError error) {
error.printStackTrace();
throw error;
} catch (Exception e) {
throw new RuntimeException("Unable to transform class", e);
} finally {
if (clazz != null) {
try {
clazz.detach();
} catch (Exception e) {
// do nothing
}
}
}
return null;
}
Aggregations