6 changed files with 312 additions and 220 deletions
@ -0,0 +1,95 @@
@@ -0,0 +1,95 @@
|
||||
/* |
||||
* Copyright 2002-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import java.lang.reflect.Field; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import org.springframework.asm.AnnotationVisitor; |
||||
import org.springframework.asm.SpringAsmInfo; |
||||
import org.springframework.asm.Type; |
||||
import org.springframework.core.annotation.AnnotationAttributes; |
||||
import org.springframework.util.ReflectionUtils; |
||||
|
||||
/** |
||||
* @author Chris Beams |
||||
* @author Juergen Hoeller |
||||
* @author Phillip Webb |
||||
* @author Sam Brannen |
||||
* @since 3.1.1 |
||||
*/ |
||||
abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor { |
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass()); |
||||
|
||||
protected final AnnotationAttributes attributes; |
||||
|
||||
protected final ClassLoader classLoader; |
||||
|
||||
|
||||
public AbstractRecursiveAnnotationVisitor(ClassLoader classLoader, AnnotationAttributes attributes) { |
||||
super(SpringAsmInfo.ASM_VERSION); |
||||
this.classLoader = classLoader; |
||||
this.attributes = attributes; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void visit(String attributeName, Object attributeValue) { |
||||
this.attributes.put(attributeName, attributeValue); |
||||
} |
||||
|
||||
@Override |
||||
public AnnotationVisitor visitAnnotation(String attributeName, String asmTypeDescriptor) { |
||||
String annotationType = Type.getType(asmTypeDescriptor).getClassName(); |
||||
AnnotationAttributes nestedAttributes = new AnnotationAttributes(); |
||||
this.attributes.put(attributeName, nestedAttributes); |
||||
return new RecursiveAnnotationAttributesVisitor(annotationType, nestedAttributes, this.classLoader); |
||||
} |
||||
|
||||
@Override |
||||
public AnnotationVisitor visitArray(String attributeName) { |
||||
return new RecursiveAnnotationArrayVisitor(attributeName, this.attributes, this.classLoader); |
||||
} |
||||
|
||||
@Override |
||||
public void visitEnum(String attributeName, String asmTypeDescriptor, String attributeValue) { |
||||
Object newValue = getEnumValue(asmTypeDescriptor, attributeValue); |
||||
visit(attributeName, newValue); |
||||
} |
||||
|
||||
protected Object getEnumValue(String asmTypeDescriptor, String attributeValue) { |
||||
Object valueToUse = attributeValue; |
||||
try { |
||||
Class<?> enumType = this.classLoader.loadClass(Type.getType(asmTypeDescriptor).getClassName()); |
||||
Field enumConstant = ReflectionUtils.findField(enumType, attributeValue); |
||||
if (enumConstant != null) { |
||||
valueToUse = enumConstant.get(null); |
||||
} |
||||
} |
||||
catch (ClassNotFoundException ex) { |
||||
logger.debug("Failed to classload enum type while reading annotation metadata", ex); |
||||
} |
||||
catch (IllegalAccessException ex) { |
||||
logger.warn("Could not access enum value while reading annotation metadata", ex); |
||||
} |
||||
return valueToUse; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
/* |
||||
* Copyright 2002-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import java.lang.reflect.Array; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import org.springframework.asm.AnnotationVisitor; |
||||
import org.springframework.asm.Type; |
||||
import org.springframework.core.annotation.AnnotationAttributes; |
||||
import org.springframework.util.ObjectUtils; |
||||
|
||||
/** |
||||
* @author Chris Beams |
||||
* @author Juergen Hoeller |
||||
* @since 3.1.1 |
||||
*/ |
||||
class RecursiveAnnotationArrayVisitor extends AbstractRecursiveAnnotationVisitor { |
||||
|
||||
private final String attributeName; |
||||
|
||||
private final List<AnnotationAttributes> allNestedAttributes = new ArrayList<AnnotationAttributes>(); |
||||
|
||||
|
||||
public RecursiveAnnotationArrayVisitor( |
||||
String attributeName, AnnotationAttributes attributes, ClassLoader classLoader) { |
||||
|
||||
super(classLoader, attributes); |
||||
this.attributeName = attributeName; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void visit(String attributeName, Object attributeValue) { |
||||
Object newValue = attributeValue; |
||||
Object existingValue = this.attributes.get(this.attributeName); |
||||
if (existingValue != null) { |
||||
newValue = ObjectUtils.addObjectToArray((Object[]) existingValue, newValue); |
||||
} |
||||
else { |
||||
Class<?> arrayClass = newValue.getClass(); |
||||
if (Enum.class.isAssignableFrom(arrayClass)) { |
||||
while (arrayClass.getSuperclass() != null && !arrayClass.isEnum()) { |
||||
arrayClass = arrayClass.getSuperclass(); |
||||
} |
||||
} |
||||
Object[] newArray = (Object[]) Array.newInstance(arrayClass, 1); |
||||
newArray[0] = newValue; |
||||
newValue = newArray; |
||||
} |
||||
this.attributes.put(this.attributeName, newValue); |
||||
} |
||||
|
||||
@Override |
||||
public AnnotationVisitor visitAnnotation(String attributeName, String asmTypeDescriptor) { |
||||
String annotationType = Type.getType(asmTypeDescriptor).getClassName(); |
||||
AnnotationAttributes nestedAttributes = new AnnotationAttributes(); |
||||
this.allNestedAttributes.add(nestedAttributes); |
||||
return new RecursiveAnnotationAttributesVisitor(annotationType, nestedAttributes, this.classLoader); |
||||
} |
||||
|
||||
@Override |
||||
public void visitEnd() { |
||||
if (!this.allNestedAttributes.isEmpty()) { |
||||
this.attributes.put(this.attributeName, |
||||
this.allNestedAttributes.toArray(new AnnotationAttributes[this.allNestedAttributes.size()])); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
/* |
||||
* Copyright 2002-2014 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.Modifier; |
||||
|
||||
import org.springframework.core.annotation.AnnotationAttributes; |
||||
import org.springframework.core.annotation.AnnotationUtils; |
||||
|
||||
/** |
||||
* @author Chris Beams |
||||
* @author Juergen Hoeller |
||||
* @since 3.1.1 |
||||
*/ |
||||
class RecursiveAnnotationAttributesVisitor extends AbstractRecursiveAnnotationVisitor { |
||||
|
||||
private final String annotationType; |
||||
|
||||
|
||||
public RecursiveAnnotationAttributesVisitor( |
||||
String annotationType, AnnotationAttributes attributes, ClassLoader classLoader) { |
||||
|
||||
super(classLoader, attributes); |
||||
this.annotationType = annotationType; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public final void visitEnd() { |
||||
try { |
||||
Class<?> annotationClass = this.classLoader.loadClass(this.annotationType); |
||||
doVisitEnd(annotationClass); |
||||
} |
||||
catch (ClassNotFoundException ex) { |
||||
logger.debug("Failed to class-load type while reading annotation metadata. " + |
||||
"This is a non-fatal error, but certain annotation metadata may be unavailable.", ex); |
||||
} |
||||
} |
||||
|
||||
protected void doVisitEnd(Class<?> annotationClass) { |
||||
registerDefaultValues(annotationClass); |
||||
} |
||||
|
||||
private void registerDefaultValues(Class<?> annotationClass) { |
||||
// Only do further scanning for public annotations; we'd run into
|
||||
// IllegalAccessExceptions otherwise, and we don't want to mess with
|
||||
// accessibility in a SecurityManager environment.
|
||||
if (Modifier.isPublic(annotationClass.getModifiers())) { |
||||
// Check declared default values of attributes in the annotation type.
|
||||
Method[] annotationAttributes = annotationClass.getMethods(); |
||||
for (Method annotationAttribute : annotationAttributes) { |
||||
String attributeName = annotationAttribute.getName(); |
||||
Object defaultValue = annotationAttribute.getDefaultValue(); |
||||
if (defaultValue != null && !this.attributes.containsKey(attributeName)) { |
||||
if (defaultValue instanceof Annotation) { |
||||
defaultValue = AnnotationAttributes.fromMap(AnnotationUtils.getAnnotationAttributes( |
||||
(Annotation) defaultValue, false, true)); |
||||
} |
||||
else if (defaultValue instanceof Annotation[]) { |
||||
Annotation[] realAnnotations = (Annotation[]) defaultValue; |
||||
AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length]; |
||||
for (int i = 0; i < realAnnotations.length; i++) { |
||||
mappedAnnotations[i] = AnnotationAttributes.fromMap( |
||||
AnnotationUtils.getAnnotationAttributes(realAnnotations[i], false, true)); |
||||
} |
||||
defaultValue = mappedAnnotations; |
||||
} |
||||
this.attributes.put(attributeName, defaultValue); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue