@SuppressWarnings("unchecked") static <A extends Annotation> A synthesizeAnnotation(A annotation, @Nullable Object annotatedElement) { if (annotation instanceof SynthesizedAnnotation || hasPlainJavaAnnotationsOnly(annotatedElement)) { return annotation; } Class<? extends Annotation> annotationType = annotation.annotationType(); if (!isSynthesizable(annotationType)) { return annotation; } DefaultAnnotationAttributeExtractor attributeExtractor = new DefaultAnnotationAttributeExtractor(annotation, annotatedElement); InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor); // Can always expose Spring's SynthesizedAnnotation marker since we explicitly check for a // synthesizable annotation before (which needs to declare @AliasFor from the same package) Class<?>[] exposedInterfaces = new Class<?>[] {annotationType, SynthesizedAnnotation.class}; return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (ReflectionUtils.isEqualsMethod(method)) { return annotationEquals(args[0]); } if (ReflectionUtils.isHashCodeMethod(method)) { return annotationHashCode(); } if (ReflectionUtils.isToStringMethod(method)) { return annotationToString(); } if (AnnotationUtils.isAnnotationTypeMethod(method)) { return annotationType(); } if (!AnnotationUtils.isAttributeMethod(method)) { throw new AnnotationConfigurationException(String.format( "Method [%s] is unsupported for synthesized annotation type [%s]", method, annotationType())); } return getAttributeValue(method); }
/** * See {@link Annotation#toString()} for guidelines on the recommended format. */ private String annotationToString() { StringBuilder sb = new StringBuilder("@").append(annotationType().getName()).append("("); Iterator<Method> iterator = AnnotationUtils.getAttributeMethods(annotationType()).iterator(); while (iterator.hasNext()) { Method attributeMethod = iterator.next(); sb.append(attributeMethod.getName()); sb.append('='); sb.append(attributeValueToString(getAttributeValue(attributeMethod))); sb.append(iterator.hasNext() ? ", " : ""); } return sb.append(")").toString(); }
/** * See {@link Annotation#hashCode()} for a definition of the required algorithm. */ private int annotationHashCode() { int result = 0; for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType())) { Object value = getAttributeValue(attributeMethod); int hashCode; if (value.getClass().isArray()) { hashCode = hashCodeForArray(value); } else { hashCode = value.hashCode(); } result += (127 * attributeMethod.getName().hashCode()) ^ hashCode; } return result; }
/** * See {@link Annotation#equals(Object)} for a definition of the required algorithm. * @param other the other object to compare against */ private boolean annotationEquals(Object other) { if (this == other) { return true; } if (!annotationType().isInstance(other)) { return false; } for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType())) { Object thisValue = getAttributeValue(attributeMethod); Object otherValue = ReflectionUtils.invokeMethod(attributeMethod, other); if (!ObjectUtils.nullSafeEquals(thisValue, otherValue)) { return false; } } return true; }
private Object getAttributeValue(Method attributeMethod) { String attributeName = attributeMethod.getName(); Object value = this.valueCache.get(attributeName); if (value == null) { value = this.attributeExtractor.getAttributeValue(attributeMethod); if (value == null) { String msg = String.format("%s returned null for attribute name [%s] from attribute source [%s]", this.attributeExtractor.getClass().getName(), attributeName, this.attributeExtractor.getSource()); throw new IllegalStateException(msg); } // Synthesize nested annotations before returning them. if (value instanceof Annotation) { value = AnnotationUtils.synthesizeAnnotation((Annotation) value, this.attributeExtractor.getAnnotatedElement()); } else if (value instanceof Annotation[]) { value = AnnotationUtils.synthesizeAnnotationArray((Annotation[]) value, this.attributeExtractor.getAnnotatedElement()); } this.valueCache.put(attributeName, value); } // Clone arrays so that users cannot alter the contents of values in our cache. if (value.getClass().isArray()) { value = cloneArray(value); } return value; }
/** * See {@link Annotation#hashCode()} for a definition of the required algorithm. */ private int annotationHashCode() { int result = 0; for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType())) { Object value = getAttributeValue(attributeMethod); int hashCode; if (value.getClass().isArray()) { hashCode = hashCodeForArray(value); } else { hashCode = value.hashCode(); } result += (127 * attributeMethod.getName().hashCode()) ^ hashCode; } return result; }
/** * See {@link Annotation#equals(Object)} for a definition of the required algorithm. * @param other the other object to compare against */ private boolean annotationEquals(Object other) { if (this == other) { return true; } if (!annotationType().isInstance(other)) { return false; } for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType())) { Object thisValue = getAttributeValue(attributeMethod); Object otherValue = ReflectionUtils.invokeMethod(attributeMethod, other); if (!ObjectUtils.nullSafeEquals(thisValue, otherValue)) { return false; } } return true; }
private Object getAttributeValue(Method attributeMethod) { String attributeName = attributeMethod.getName(); Object value = this.valueCache.get(attributeName); if (value == null) { value = this.attributeExtractor.getAttributeValue(attributeMethod); if (value == null) { String msg = String.format("%s returned null for attribute name [%s] from attribute source [%s]", this.attributeExtractor.getClass().getName(), attributeName, this.attributeExtractor.getSource()); throw new IllegalStateException(msg); } // Synthesize nested annotations before returning them. if (value instanceof Annotation) { value = AnnotationUtils.synthesizeAnnotation((Annotation) value, this.attributeExtractor.getAnnotatedElement()); } else if (value instanceof Annotation[]) { value = AnnotationUtils.synthesizeAnnotationArray((Annotation[]) value, this.attributeExtractor.getAnnotatedElement()); } this.valueCache.put(attributeName, value); } // Clone arrays so that users cannot alter the contents of values in our cache. if (value.getClass().isArray()) { value = cloneArray(value); } return value; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (ReflectionUtils.isEqualsMethod(method)) { return annotationEquals(args[0]); } if (ReflectionUtils.isHashCodeMethod(method)) { return annotationHashCode(); } if (ReflectionUtils.isToStringMethod(method)) { return annotationToString(); } if (AnnotationUtils.isAnnotationTypeMethod(method)) { return annotationType(); } if (!AnnotationUtils.isAttributeMethod(method)) { throw new AnnotationConfigurationException(String.format( "Method [%s] is unsupported for synthesized annotation type [%s]", method, annotationType())); } return getAttributeValue(method); }
/** * See {@link Annotation#toString()} for guidelines on the recommended format. */ private String annotationToString() { StringBuilder sb = new StringBuilder("@").append(annotationType().getName()).append("("); Iterator<Method> iterator = AnnotationUtils.getAttributeMethods(annotationType()).iterator(); while (iterator.hasNext()) { Method attributeMethod = iterator.next(); sb.append(attributeMethod.getName()); sb.append('='); sb.append(attributeValueToString(getAttributeValue(attributeMethod))); sb.append(iterator.hasNext() ? ", " : ""); } return sb.append(")").toString(); }
/** * See {@link Annotation#hashCode()} for a definition of the required algorithm. */ private int annotationHashCode() { int result = 0; for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType())) { Object value = getAttributeValue(attributeMethod); int hashCode; if (value.getClass().isArray()) { hashCode = hashCodeForArray(value); } else { hashCode = value.hashCode(); } result += (127 * attributeMethod.getName().hashCode()) ^ hashCode; } return result; }
/** * See {@link Annotation#equals(Object)} for a definition of the required algorithm. * @param other the other object to compare against */ private boolean annotationEquals(Object other) { if (this == other) { return true; } if (!annotationType().isInstance(other)) { return false; } for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType())) { Object thisValue = getAttributeValue(attributeMethod); Object otherValue = ReflectionUtils.invokeMethod(attributeMethod, other); if (!ObjectUtils.nullSafeEquals(thisValue, otherValue)) { return false; } } return true; }
InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor); Class<?>[] exposedInterfaces = (canExposeSynthesizedMarker(annotationType) ? new Class<?>[] {annotationType, SynthesizedAnnotation.class} : new Class<?>[] {annotationType});
private Object getAttributeValue(Method attributeMethod) { String attributeName = attributeMethod.getName(); Object value = this.valueCache.get(attributeName); if (value == null) { value = this.attributeExtractor.getAttributeValue(attributeMethod); if (value == null) { String msg = String.format("%s returned null for attribute name [%s] from attribute source [%s]", this.attributeExtractor.getClass().getName(), attributeName, this.attributeExtractor.getSource()); throw new IllegalStateException(msg); } // Synthesize nested annotations before returning them. if (value instanceof Annotation) { value = AnnotationUtils.synthesizeAnnotation((Annotation) value, this.attributeExtractor.getAnnotatedElement()); } else if (value instanceof Annotation[]) { value = AnnotationUtils.synthesizeAnnotationArray((Annotation[]) value, this.attributeExtractor.getAnnotatedElement()); } this.valueCache.put(attributeName, value); } // Clone arrays so that users cannot alter the contents of values in our cache. if (value.getClass().isArray()) { value = cloneArray(value); } return value; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (ReflectionUtils.isEqualsMethod(method)) { return annotationEquals(args[0]); } if (ReflectionUtils.isHashCodeMethod(method)) { return annotationHashCode(); } if (ReflectionUtils.isToStringMethod(method)) { return annotationToString(); } if (AnnotationUtils.isAnnotationTypeMethod(method)) { return annotationType(); } if (!AnnotationUtils.isAttributeMethod(method)) { throw new AnnotationConfigurationException(String.format( "Method [%s] is unsupported for synthesized annotation type [%s]", method, annotationType())); } return getAttributeValue(method); }
/** * See {@link Annotation#toString()} for guidelines on the recommended format. */ private String annotationToString() { StringBuilder sb = new StringBuilder("@").append(annotationType().getName()).append("("); Iterator<Method> iterator = AnnotationUtils.getAttributeMethods(annotationType()).iterator(); while (iterator.hasNext()) { Method attributeMethod = iterator.next(); sb.append(attributeMethod.getName()); sb.append('='); sb.append(attributeValueToString(getAttributeValue(attributeMethod))); sb.append(iterator.hasNext() ? ", " : ""); } return sb.append(")").toString(); }
/** * See {@link Annotation#hashCode()} for a definition of the required algorithm. */ private int annotationHashCode() { int result = 0; for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType())) { Object value = getAttributeValue(attributeMethod); int hashCode; if (value.getClass().isArray()) { hashCode = hashCodeForArray(value); } else { hashCode = value.hashCode(); } result += (127 * attributeMethod.getName().hashCode()) ^ hashCode; } return result; }
/** * See {@link Annotation#equals(Object)} for a definition of the required algorithm. * @param other the other object to compare against */ private boolean annotationEquals(Object other) { if (this == other) { return true; } if (!annotationType().isInstance(other)) { return false; } for (Method attributeMethod : AnnotationUtils.getAttributeMethods(annotationType())) { Object thisValue = getAttributeValue(attributeMethod); Object otherValue = ReflectionUtils.invokeMethod(attributeMethod, other); if (!ObjectUtils.nullSafeEquals(thisValue, otherValue)) { return false; } } return true; }
@SuppressWarnings("unchecked") static <A extends Annotation> A synthesizeAnnotation(A annotation, @Nullable Object annotatedElement) { if (annotation instanceof SynthesizedAnnotation || hasPlainJavaAnnotationsOnly(annotatedElement)) { return annotation; } Class<? extends Annotation> annotationType = annotation.annotationType(); if (!isSynthesizable(annotationType)) { return annotation; } DefaultAnnotationAttributeExtractor attributeExtractor = new DefaultAnnotationAttributeExtractor(annotation, annotatedElement); InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor); // Can always expose Spring's SynthesizedAnnotation marker since we explicitly check for a // synthesizable annotation before (which needs to declare @AliasFor from the same package) Class<?>[] exposedInterfaces = new Class<?>[] {annotationType, SynthesizedAnnotation.class}; return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler); }