Search in sources :

Example 86 with CtConstructor

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");
}
Also used : CtBehavior(javassist.CtBehavior) MethodInfo(javassist.bytecode.MethodInfo) CtConstructor(javassist.CtConstructor)

Example 87 with CtConstructor

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());
    }
}
Also used : CtClass(javassist.CtClass) NotFoundException(javassist.NotFoundException) CtMethod(javassist.CtMethod) CtConstructor(javassist.CtConstructor)

Example 88 with CtConstructor

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());
    }
}
Also used : CtClass(javassist.CtClass) NotFoundException(javassist.NotFoundException) CtMethod(javassist.CtMethod) CtConstructor(javassist.CtConstructor)

Example 89 with CtConstructor

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();
}
Also used : MethodRef(com.android.dexdeps.MethodRef) ArrayList(java.util.ArrayList) CtMethod(javassist.CtMethod) CtConstructor(javassist.CtConstructor)

Example 90 with CtConstructor

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;
}
Also used : ConstPool(javassist.bytecode.ConstPool) StringMemberValue(javassist.bytecode.annotation.StringMemberValue) ClassPool(javassist.ClassPool) ArrayList(java.util.ArrayList) NotFoundException(javassist.NotFoundException) CtField(javassist.CtField) AnnotationMemberValue(javassist.bytecode.annotation.AnnotationMemberValue) BooleanMemberValue(javassist.bytecode.annotation.BooleanMemberValue) ClassFile(javassist.bytecode.ClassFile) AnnotationsAttribute(javassist.bytecode.AnnotationsAttribute) LoaderClassPath(javassist.LoaderClassPath) Annotation(javassist.bytecode.annotation.Annotation) NotFoundException(javassist.NotFoundException) IllegalClassFormatException(java.lang.instrument.IllegalClassFormatException) CtConstructor(javassist.CtConstructor) CtClass(javassist.CtClass) ByteArrayInputStream(java.io.ByteArrayInputStream) MemberValue(javassist.bytecode.annotation.MemberValue) AnnotationMemberValue(javassist.bytecode.annotation.AnnotationMemberValue) ArrayMemberValue(javassist.bytecode.annotation.ArrayMemberValue) BooleanMemberValue(javassist.bytecode.annotation.BooleanMemberValue) StringMemberValue(javassist.bytecode.annotation.StringMemberValue) ArrayMemberValue(javassist.bytecode.annotation.ArrayMemberValue) CtMethod(javassist.CtMethod)

Aggregations

CtConstructor (javassist.CtConstructor)91 CtClass (javassist.CtClass)66 CtMethod (javassist.CtMethod)38 NotFoundException (javassist.NotFoundException)33 ClassPool (javassist.ClassPool)30 CtField (javassist.CtField)30 CannotCompileException (javassist.CannotCompileException)29 IOException (java.io.IOException)13 Method (java.lang.reflect.Method)9 ArrayList (java.util.ArrayList)7 FileNotFoundException (java.io.FileNotFoundException)6 CtNewMethod (javassist.CtNewMethod)6 MethodInfo (javassist.bytecode.MethodInfo)6 StorageException (org.apache.skywalking.oap.server.core.storage.StorageException)6 StringWriter (java.io.StringWriter)5 ConstPool (javassist.bytecode.ConstPool)5 HashMap (java.util.HashMap)4 Annotation (javassist.bytecode.annotation.Annotation)4 OALCompileException (org.apache.skywalking.oap.server.core.oal.rt.OALCompileException)4 ModuleStartException (org.apache.skywalking.oap.server.library.module.ModuleStartException)4