Example usage for java.lang ClassCircularityError printStackTrace

List of usage examples for java.lang ClassCircularityError printStackTrace

Introduction

In this page you can find the example usage for java.lang ClassCircularityError printStackTrace.

Prototype

public void printStackTrace() 

Source Link

Document

Prints this throwable and its backtrace to the standard error stream.

Usage

From source file:org.broadleafcommerce.common.extensibility.jpa.copy.DirectCopyClassTransformer.java

@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;
    }//from www  .j a  v a 2s. c om

    //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());

                        // Look through all of the constructors in the implClass to see
                        // 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;
}