public static DialogFieldConfig getDialogFieldFromSuperClasses(CtMethod method) throws NotFoundException, ClassNotFoundException, InvalidComponentClassException { DialogFieldConfig dialogFieldConfig = null; List<CtClass> classes = new ArrayList<CtClass>(); CtClass clazz = method.getDeclaringClass(); classes.add(clazz); while (clazz.getSuperclass() != null) { classes.add(clazz.getSuperclass()); clazz = clazz.getSuperclass(); } Collections.reverse(classes); CtMember interfaceMember = getMemberForAnnotatedInterfaceMethod(method); if (interfaceMember != null) { dialogFieldConfig = new DialogFieldConfig( (DialogField) interfaceMember.getAnnotation(DialogField.class), interfaceMember); } for (CtClass ctclass : classes) { try { CtMethod superClassMethod = ctclass.getDeclaredMethod(method.getName(), method.getParameterTypes()); if (superClassMethod.hasAnnotation(DialogField.class)) { dialogFieldConfig = new DialogFieldConfig( (DialogField) superClassMethod.getAnnotation(DialogField.class), superClassMethod); } else if (superClassMethod.hasAnnotation(DialogFieldOverride.class)) { mergeDialogFields(dialogFieldConfig, superClassMethod); } } catch (NotFoundException e) { } } return dialogFieldConfig; }
private void enhanceJPACallback(CtClass ctClass, CtMethod method, Class anno) throws Exception { if (method.hasAnnotation(anno)) { CtMethod ctMethod = CtMethod.make( format( "public void {}() {\n" + " net.csdn.jpa.context.JPAContext jpaContext = getJPAConfig().reInitJPAContext();\n" + " try {\n" + " {}();\n" + " getJPAConfig().getJPAContext().closeTx(false);\n" + " } catch (Exception e) {\n" + " getJPAConfig().getJPAContext().closeTx(true);\n" + " } finally {\n" + " getJPAConfig().setJPAContext(jpaContext);\n" + " }\n" + " }", "$_" + method.getName(), method.getName()), ctClass); ctClass.addMethod(ctMethod); AnnotationsAttribute annotationsAttribute = EnhancerHelper.getAnnotations(ctMethod); EnhancerHelper.createAnnotation(annotationsAttribute, callback_classes.get(anno)); } }
private static void mergeDialogFields(DialogFieldConfig dialogFieldConfig, CtMethod method) throws ClassNotFoundException { if (dialogFieldConfig != null && method.hasAnnotation(DialogFieldOverride.class)) { DialogFieldOverride dialogField = (DialogFieldOverride) method.getAnnotation(DialogFieldOverride.class); if (StringUtils.isNotEmpty(dialogField.fieldLabel())) { dialogFieldConfig.setFieldLabel(dialogField.fieldLabel()); } if (StringUtils.isNotEmpty(dialogField.fieldDescription())) { dialogFieldConfig.setFieldDescription(dialogField.fieldDescription()); } dialogFieldConfig.setRequired(dialogField.required()); dialogFieldConfig.setHideLabel(dialogField.hideLabel()); if (StringUtils.isNotEmpty(dialogField.defaultValue())) { dialogFieldConfig.setDefaultValue(dialogField.defaultValue()); } if (StringUtils.isNotEmpty(dialogField.name())) { dialogFieldConfig.setName(dialogField.name()); } dialogFieldConfig.setTab(dialogField.tab()); dialogFieldConfig.setRanking(dialogField.ranking()); if (dialogField.additionalProperties().length > 0) { List<FieldProperty> properties = new ArrayList<FieldProperty>(); properties.addAll(Arrays.asList(dialogField.additionalProperties())); if (dialogField.mergeAdditionalProperties()) { properties.addAll(Arrays.asList(dialogFieldConfig.getAdditionalProperties())); } dialogFieldConfig.setAdditionalProperties( properties.toArray(new FieldProperty[properties.size()])); } if (dialogField.listeners().length > 0) { List<Listener> listeners = new ArrayList<Listener>(); listeners.addAll(Arrays.asList(dialogField.listeners())); if (dialogField.mergeAdditionalProperties()) { listeners.addAll(Arrays.asList(dialogFieldConfig.getListeners())); } dialogFieldConfig.setListeners(listeners.toArray(new Listener[listeners.size()])); } } }
private Set<CtMethod> getPatchMethods(Set<CtClass> patchClasses) { Set<CtMethod> result = new HashSet<CtMethod>(); // add all @PatchMethod found in a temporary map Map<String, List<CtMethod>> temp = new HashMap<String, List<CtMethod>>(); for (CtClass patchClass : patchClasses) { for (CtMethod ctMethod : patchClass.getDeclaredMethods()) { if (ctMethod.hasAnnotation(PatchMethod.class)) { if (!Modifier.isStatic(ctMethod.getModifiers())) { throw new GwtTestPatchException( "@" + PatchMethod.class.getName() + " has to be static : '" + ctMethod.getLongName() + "'"); } String nameAndSignature = ctMethod.getName() + Descriptor.toString(ctMethod.getSignature()); List<CtMethod> correspondingMethods = temp.get(nameAndSignature); if (correspondingMethods == null) { correspondingMethods = new ArrayList<CtMethod>(); temp.put(nameAndSignature, correspondingMethods); } correspondingMethods.add(ctMethod); } } } // for each @PatchMethod with the same signature, filter to get one with // override=true for (Map.Entry<String, List<CtMethod>> entry : temp.entrySet()) { CtMethod methodToUse = getMethodToUse(entry.getValue(), PatchMethod.class); methodToUse.setModifiers(Modifier.PUBLIC + Modifier.STATIC); result.add(methodToUse); } return result; }
private CtMethod getInitMethod(Set<CtClass> patchClasses) { List<CtMethod> initMethods = new ArrayList<CtMethod>(); for (CtClass patchClass : patchClasses) { for (CtMethod ctMethod : patchClass.getDeclaredMethods()) { if (ctMethod.hasAnnotation(InitMethod.class)) { if (!Modifier.isStatic(ctMethod.getModifiers())) { throw new GwtTestPatchException( "@" + InitMethod.class.getName() + " has to be static : '" + ctMethod.getLongName() + "'"); } try { if (ctMethod.getParameterTypes().length != 1 || ctMethod.getParameterTypes()[0] != GwtClassPool.getCtClass(CtClass.class)) { throw new GwtTestPatchException( "@" + InitMethod.class.getName() + " method must have one and only one parameter of type '" + CtClass.class.getName() + "'"); } } catch (NotFoundException e) { // should never happen throw new GwtTestPatchException(e); } initMethods.add(ctMethod); } } } CtMethod initMethod = getMethodToUse(initMethods, InitMethod.class); if (initMethod != null) { initMethod.setModifiers(Modifier.PUBLIC + Modifier.STATIC); } return initMethod; }
@Override public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { byte[] bytes = null; try { final ClassPool pool = ClassPool.getDefault(); pool.appendClassPath(new LoaderClassPath(getClass().getClassLoader())); final CtClass ctClass = pool.getCtClass(className.replaceAll("/", ".")); if (ctClass != null) { try { for (CtMethod ctMethod : ctClass.getMethods()) { if (ctMethod.hasAnnotation(Retryable.class)) { try { changeMethod(ctClass, ctMethod); bytes = ctClass.toBytecode(); writeClassFile(bytes); } catch (CannotCompileException | IOException e) { e.printStackTrace(); } System.out.println("found it!"); } } } finally { ctClass.detach(); } } } catch (NotFoundException e) { e.printStackTrace(); } return bytes; }
private void enhanceJPACallback(CtClass ctClass) throws Exception { CtMethod[] methods = ctClass.getDeclaredMethods(); for (CtMethod ctMethod : methods) { if (ctMethod.hasAnnotation(AfterSave.class)) { enhanceJPACallback(ctClass, ctMethod, AfterSave.class); } if (ctMethod.hasAnnotation(BeforeSave.class)) { enhanceJPACallback(ctClass, ctMethod, BeforeSave.class); } if (ctMethod.hasAnnotation(AfterUpdate.class)) { enhanceJPACallback(ctClass, ctMethod, AfterUpdate.class); } if (ctMethod.hasAnnotation(BeforeUpdate.class)) { enhanceJPACallback(ctClass, ctMethod, BeforeUpdate.class); } if (ctMethod.hasAnnotation(BeforeDestroy.class)) { enhanceJPACallback(ctClass, ctMethod, BeforeDestroy.class); } if (ctMethod.hasAnnotation(AfterLoad.class)) { enhanceJPACallback(ctClass, ctMethod, AfterLoad.class); } } }
@Override public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { // 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; } } } templates.add(templateTokens.get(val)); } } } 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.lifecycle( LifeCycleEvent.START, String.format( "Transform - Copying into [%s] from [%s]", 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[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[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[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[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.lifecycle( LifeCycleEvent.END, String.format( "Transform - Copying into [%s] from [%s]", 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) { clazz.detach(); } } return null; }
@Override public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { String convertedClassName = className.replace('/', '.'); if (xformTemplates.containsKey(convertedClassName)) { String xformKey = convertedClassName; String[] xformVals = xformTemplates.get(xformKey).split(","); logger.lifecycle( LifeCycleEvent.START, String.format( "Transform - Copying into [%s] from [%s]", xformKey, StringUtils.join(xformVals, ","))); try { // Load the destination class and defrost it so it is eligible for modifications ClassPool classPool = ClassPool.getDefault(); CtClass clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false); clazz.defrost(); 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) { logger.debug(String.format("Adding interface [%s]", i.getName())); clazz.addInterface(i); } // 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 { 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 (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())); 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); } } } logger.lifecycle( LifeCycleEvent.END, String.format( "Transform - Copying into [%s] from [%s]", xformKey, StringUtils.join(xformVals, ","))); return clazz.toBytecode(); } catch (Exception e) { throw new RuntimeException("Unable to transform class", e); } } return null; }
/** * Constructs a list of Dialog objects based on Classes annotated by Component annotations. Scans * the provided list of classes constructing a Dialog object for each one annotated with the * Component annotation. Any classes provided in the class list which are not thusly annotated are * ignored. * * @param classList * @param zipOutputStream * @param reservedNames * @param xtypeMap * @param classLoader * @param classPool * @return A list of constructed Dialog objects * @throws InvalidComponentClassException * @throws InvalidComponentFieldException * @throws OutputFailureException * @throws IOException * @throws ParserConfigurationException * @throws TransformerException * @throws ClassNotFoundException * @throws CannotCompileException * @throws NotFoundException * @throws SecurityException * @throws NoSuchFieldException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException * @throws InstantiationException */ public static List<Dialog> buildDialogsFromClassList( ComponentNameTransformer transformer, List<CtClass> classList, ZipArchiveOutputStream zipOutputStream, Set<String> reservedNames, WidgetRegistry widgetRegistry, ClassLoader classLoader, ClassPool classPool, File buildDirectory, String componentPathBase, String defaultComponentPathSuffix) throws InvalidComponentClassException, InvalidComponentFieldException, OutputFailureException, IOException, ParserConfigurationException, TransformerException, ClassNotFoundException, CannotCompileException, NotFoundException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException { final List<Dialog> dialogList = new ArrayList<Dialog>(); for (CtClass curClass : classList) { ComponentMojoUtil.getLog().debug("Checking class for Component annotation " + curClass); boolean hasDialogFieldOrCQIncludeTab = false; for (CtField curField : ComponentMojoUtil.collectFields(curClass)) { if (curField.hasAnnotation(DialogField.class)) { hasDialogFieldOrCQIncludeTab = true; break; } } if (!hasDialogFieldOrCQIncludeTab) { for (CtMethod curMethod : ComponentMojoUtil.collectMethods(curClass)) { if (curMethod.hasAnnotation(DialogField.class)) { hasDialogFieldOrCQIncludeTab = true; break; } } } if (!hasDialogFieldOrCQIncludeTab) { Component componentAnnotation = (Component) curClass.getAnnotation(Component.class); for (Tab tab : componentAnnotation.tabs()) { if (StringUtils.isNotEmpty(tab.path())) { hasDialogFieldOrCQIncludeTab = true; break; } } } if (hasDialogFieldOrCQIncludeTab) { ComponentMojoUtil.getLog().debug("Processing Component Class " + curClass); Dialog builtDialog = DialogFactory.make(curClass, widgetRegistry, classLoader, classPool); dialogList.add(builtDialog); File dialogFile = writeDialogToFile( transformer, builtDialog, curClass, buildDirectory, componentPathBase, defaultComponentPathSuffix); writeDialogToArchiveFile( transformer, dialogFile, curClass, zipOutputStream, reservedNames, componentPathBase, defaultComponentPathSuffix); } } return dialogList; }