Author: musachy
Date: Fri Mar 2 21:23:01 2007
New Revision: 514081
URL: http://svn.apache.org/viewvc?view=rev&rev=514081
Log:
WW-1675 Modify Struts Annotations to scan compiled classes for annotations
@StrutsTagSkipInheritance was added to stop class hierarchy scanning for Struts
tag annotations
Modified:
struts/maven/trunk/struts-annotations/src/main/java/org/apache/struts/annotations/taglib/apt/TagAnnotationProcessor.java
Modified:
struts/maven/trunk/struts-annotations/src/main/java/org/apache/struts/annotations/taglib/apt/TagAnnotationProcessor.java
URL:
http://svn.apache.org/viewvc/struts/maven/trunk/struts-annotations/src/main/java/org/apache/struts/annotations/taglib/apt/TagAnnotationProcessor.java?view=diff&rev=514081&r1=514080&r2=514081
==============================================================================
---
struts/maven/trunk/struts-annotations/src/main/java/org/apache/struts/annotations/taglib/apt/TagAnnotationProcessor.java
(original)
+++
struts/maven/trunk/struts-annotations/src/main/java/org/apache/struts/annotations/taglib/apt/TagAnnotationProcessor.java
Fri Mar 2 21:23:01 2007
@@ -20,11 +20,19 @@
*/
package org.apache.struts.annotations.taglib.apt;
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.TreeMap;
@@ -61,6 +69,7 @@
public class TagAnnotationProcessor implements AnnotationProcessor {
public static final String TAG =
"org.apache.struts2.views.annotations.StrutsTag";
public static final String TAG_ATTRIBUTE =
"org.apache.struts2.views.annotations.StrutsTagAttribute";
+ public static final String TAG_SKIP_HIERARCHY =
"org.apache.struts2.views.annotations.StrutsTagSkipInheritance";
private AnnotationProcessorEnvironment environment;
private AnnotationTypeDeclaration tagDeclaration;
@@ -113,7 +122,6 @@
tagAttributeDeclaration);
// create Attribute and apply values found
TagAttribute attribute = new TagAttribute();
- attribute.setDescription((String) values.get("description"));
String name = (String) values.get("name");
if (name == null || name.length() == 0) {
// get name from method
@@ -122,11 +130,8 @@
.charAt(3)))
+ methodName.substring(4);
}
- attribute.setName(name);
- attribute.setRequired((Boolean) values.get("required"));
- attribute.setRtexprvalue((Boolean) values.get("rtexprvalue"));
- attribute.setDefaultValue((String) values.get("defaultValue"));
- attribute.setType((String) values.get("type"));
+ values.put("name", name);
+ populateTagAttributes(attribute, values);
// add to map
Tag parentTag = tags.get(typeName);
if (parentTag != null)
@@ -153,23 +158,74 @@
saveTemplates();
}
+ private void populateTagAttributes(TagAttribute attribute, Map<String,
Object> values) {
+ attribute.setRequired((Boolean) values.get("required"));
+ attribute.setRtexprvalue((Boolean) values.get("rtexprvalue"));
+ attribute.setDefaultValue((String) values.get("defaultValue"));
+ attribute.setType((String) values.get("type"));
+ attribute.setDescription((String) values.get("description"));
+ attribute.setName((String) values.get("name"));
+ }
+
private void processHierarchy(Tag tag) {
try {
Class clazz = Class.forName(tag.getDeclaredType());
- while ((clazz = clazz.getSuperclass()) != null) {
+ //skip hierarchy processing if the class is marked with the skip
annotation
+ while(getAnnotation(TAG_SKIP_HIERARCHY, clazz.getAnnotations()) ==
null
+ && ((clazz = clazz.getSuperclass()) != null)) {
Tag parentTag = tags.get(clazz.getName());
// copy parent annotations to this tag
- if (parentTag != null) {
- for (TagAttribute attribute : parentTag.getAttributes()) {
+ if(parentTag != null) {
+ for(TagAttribute attribute : parentTag.getAttributes()) {
+ tag.addTagAttribute(attribute);
+ }
+ } else {
+ // Maybe the parent class is already compiled
+ addTagAttributesFromParent(tag, clazz);
+ }
+ }
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void addTagAttributesFromParent(Tag tag, Class clazz) throws
ClassNotFoundException {
+ try {
+ BeanInfo info = Introspector.getBeanInfo(clazz);
+ PropertyDescriptor[] props = info.getPropertyDescriptors();
+
+ //iterate over class fields
+ for(int i = 0; i < props.length; ++i) {
+ PropertyDescriptor prop = props[i];
+ Method writeMethod = prop.getWriteMethod();
+ //make sure it is public
+ if(writeMethod != null &&
Modifier.isPublic(writeMethod.getModifiers())) {
+ //can't use the genertic getAnnotation 'cause the class it
not on this jar
+ Annotation annotation = getAnnotation(TAG_ATTRIBUTE,
writeMethod.getAnnotations());
+ if(annotation != null) {
+ Map<String, Object> values = getValues(annotation);
+ //create tag
+ TagAttribute attribute = new TagAttribute();
+ values.put("name", prop.getName());
+ populateTagAttributes(attribute, values);
tag.addTagAttribute(attribute);
}
}
+
}
- } catch (ClassNotFoundException e) {
+ } catch(Exception e) {
throw new RuntimeException(e);
}
}
+ private Annotation getAnnotation(String typeName, Annotation[]
annotations) {
+ for(int i = 0; i < annotations.length; i++) {
+ if(annotations[i].annotationType().getName().equals(typeName))
+ return annotations[i];
+ }
+ return null;
+ }
+
private void checkOptions() {
if (getOption("tlibVersion") == null)
throw new IllegalArgumentException("'tlibVersion' is missing");
@@ -340,7 +396,7 @@
/**
* Get values of annotation
- *
+ *
* @param declaration The annotation declaration
* @param type
* The type of the annotation
@@ -375,6 +431,35 @@
String name = annotationType.getSimpleName();
if (!values.containsKey(name))
values.put(name, value.getValue());
+ }
+ }
+
+ return values;
+ }
+
+ /**
+ * Get values of annotation
+ *
+ * @param annotation The annotation
+ * @return name->value map of annotation values
+ * @throws IntrospectionException
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ * @throws IllegalArgumentException
+ */
+ private Map<String, Object> getValues(Annotation annotation) throws
IntrospectionException, IllegalArgumentException, IllegalAccessException,
InvocationTargetException {
+ Map<String, Object> values = new TreeMap<String, Object>();
+ //if the tag classes were on this project we could just cast to the
right type
+ //but they are needed on core
+ Class annotationType = annotation.annotationType();
+
+ Method[] methods = annotationType.getMethods();
+ //iterate over class fields
+ for(int i = 0; i < methods.length; ++i) {
+ Method method = methods[i];
+ if(method != null && method.getParameterTypes().length == 0) {
+ Object value = method.invoke(annotation, new Object[0]);
+ values.put(method.getName(), value);
}
}