[seam-commits] Seam SVN: r11708 - modules/trunk/remoting/src/main/java/org/jboss/seam/remoting.
seam-commits at lists.jboss.org
seam-commits at lists.jboss.org
Tue Dec 1 05:53:57 EST 2009
Author: shane.bryzak at jboss.com
Date: 2009-12-01 05:53:56 -0500 (Tue, 01 Dec 2009)
New Revision: 11708
Added:
modules/trunk/remoting/src/main/java/org/jboss/seam/remoting/AnnotationInvocationHandler.java
Modified:
modules/trunk/remoting/src/main/java/org/jboss/seam/remoting/AnnotationsParser.java
Log:
support for qualifiers with literal member values
Added: modules/trunk/remoting/src/main/java/org/jboss/seam/remoting/AnnotationInvocationHandler.java
===================================================================
--- modules/trunk/remoting/src/main/java/org/jboss/seam/remoting/AnnotationInvocationHandler.java (rev 0)
+++ modules/trunk/remoting/src/main/java/org/jboss/seam/remoting/AnnotationInvocationHandler.java 2009-12-01 10:53:56 UTC (rev 11708)
@@ -0,0 +1,300 @@
+package org.jboss.seam.remoting;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ *
+ * @author Shane Bryzak
+ */
+public class AnnotationInvocationHandler implements InvocationHandler
+{
+ private Class<? extends Annotation> annotationType;
+
+ private Map<String,Object> memberValues;
+
+ public AnnotationInvocationHandler(Class<? extends Annotation> annotationType,
+ Map<String,Object> memberValues)
+ {
+ this.annotationType = annotationType;
+ this.memberValues = memberValues;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable
+ {
+ if ("annotationType".equals(method.getName()))
+ {
+ return annotationType;
+ }
+ else if ("equals".equals(method.getName()))
+ {
+ return equals(args[0]);
+ }
+ else if ("hashCode".equals(method.getName()))
+ {
+ return hashCode();
+ }
+ else if ("toString".equals(method.getName()))
+ {
+ return toString();
+ }
+ else
+ {
+ return memberValues.get(method.getName());
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder string = new StringBuilder();
+ string.append('@').append(annotationType.getName()).append('(');
+ for (int i = 0; i < annotationType.getDeclaredMethods().length; i++)
+ {
+ string.append(annotationType.getDeclaredMethods()[i].getName()).append('=');
+ Object value = invoke(annotationType.getDeclaredMethods()[i], this);
+ if (value instanceof boolean[])
+ {
+ appendInBraces(string, Arrays.toString((boolean[]) value));
+ }
+ else if (value instanceof byte[])
+ {
+ appendInBraces(string, Arrays.toString((byte[]) value));
+ }
+ else if (value instanceof short[])
+ {
+ appendInBraces(string, Arrays.toString((short[]) value));
+ }
+ else if (value instanceof int[])
+ {
+ appendInBraces(string, Arrays.toString((int[]) value));
+ }
+ else if (value instanceof long[])
+ {
+ appendInBraces(string, Arrays.toString((long[]) value));
+ }
+ else if (value instanceof float[])
+ {
+ appendInBraces(string, Arrays.toString((float[]) value));
+ }
+ else if (value instanceof double[])
+ {
+ appendInBraces(string, Arrays.toString((double[]) value));
+ }
+ else if (value instanceof char[])
+ {
+ appendInBraces(string, Arrays.toString((char[]) value));
+ }
+ else if (value instanceof String[])
+ {
+ String[] strings = (String[]) value;
+ String[] quoted = new String[strings.length];
+ for (int j = 0; j < strings.length; j++)
+ {
+ quoted[j] = "\"" + strings[j] + "\"";
+ }
+ appendInBraces(string, Arrays.toString(quoted));
+ }
+ else if (value instanceof Class<?>[])
+ {
+ Class<?>[] classes = (Class<?>[]) value;
+ String[] names = new String[classes.length];
+ for (int j = 0; j < classes.length; j++)
+ {
+ names[j] = classes[j].getName() + ".class";
+ }
+ appendInBraces(string, Arrays.toString(names));
+ }
+ else if (value instanceof Object[])
+ {
+ appendInBraces(string, Arrays.toString((Object[]) value));
+ }
+ else if (value instanceof String)
+ {
+ string.append('"').append(value).append('"');
+ }
+ else if (value instanceof Class<?>)
+ {
+ string.append(((Class<?>) value).getName()).append(".class");
+ }
+ else
+ {
+ string.append(value);
+ }
+ if (i < annotationType.getDeclaredMethods().length - 1)
+ {
+ string.append(", ");
+ }
+ }
+ return string.append(')').toString();
+ }
+
+ private void appendInBraces(StringBuilder buf, String s)
+ {
+ buf.append('{').append(s.substring(1, s.length() - 1)).append('}');
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if (other instanceof Annotation)
+ {
+ Annotation that = (Annotation) other;
+ if (this.annotationType.equals(that.annotationType()))
+ {
+ for (Method member : annotationType.getDeclaredMethods())
+ {
+ Object thisValue = memberValues.get(member.getName());
+ Object thatValue = invoke(member, that);
+ if (thisValue instanceof byte[] && thatValue instanceof byte[])
+ {
+ if (!Arrays.equals((byte[]) thisValue, (byte[]) thatValue))
+ return false;
+ }
+ else if (thisValue instanceof short[]
+ && thatValue instanceof short[])
+ {
+ if (!Arrays.equals((short[]) thisValue, (short[]) thatValue))
+ return false;
+ }
+ else if (thisValue instanceof int[]
+ && thatValue instanceof int[])
+ {
+ if (!Arrays.equals((int[]) thisValue, (int[]) thatValue))
+ return false;
+ }
+ else if (thisValue instanceof long[]
+ && thatValue instanceof long[])
+ {
+ if (!Arrays.equals((long[]) thisValue, (long[]) thatValue))
+ return false;
+ }
+ else if (thisValue instanceof float[]
+ && thatValue instanceof float[])
+ {
+ if (!Arrays.equals((float[]) thisValue, (float[]) thatValue))
+ return false;
+ }
+ else if (thisValue instanceof double[]
+ && thatValue instanceof double[])
+ {
+ if (!Arrays
+ .equals((double[]) thisValue, (double[]) thatValue))
+ return false;
+ }
+ else if (thisValue instanceof char[]
+ && thatValue instanceof char[])
+ {
+ if (!Arrays.equals((char[]) thisValue, (char[]) thatValue))
+ return false;
+ }
+ else if (thisValue instanceof boolean[]
+ && thatValue instanceof boolean[])
+ {
+ if (!Arrays.equals((boolean[]) thisValue,
+ (boolean[]) thatValue))
+ return false;
+ }
+ else if (thisValue instanceof Object[]
+ && thatValue instanceof Object[])
+ {
+ if (!Arrays
+ .equals((Object[]) thisValue, (Object[]) thatValue))
+ return false;
+ }
+ else
+ {
+ if (!thisValue.equals(thatValue))
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hashCode = 0;
+ for (Method member : annotationType.getDeclaredMethods())
+ {
+ int memberNameHashCode = 127 * member.getName().hashCode();
+ Object value = memberValues.get(member.getName());
+ int memberValueHashCode;
+ if (value instanceof boolean[])
+ {
+ memberValueHashCode = Arrays.hashCode((boolean[]) value);
+ }
+ else if (value instanceof short[])
+ {
+ memberValueHashCode = Arrays.hashCode((short[]) value);
+ }
+ else if (value instanceof int[])
+ {
+ memberValueHashCode = Arrays.hashCode((int[]) value);
+ }
+ else if (value instanceof long[])
+ {
+ memberValueHashCode = Arrays.hashCode((long[]) value);
+ }
+ else if (value instanceof float[])
+ {
+ memberValueHashCode = Arrays.hashCode((float[]) value);
+ }
+ else if (value instanceof double[])
+ {
+ memberValueHashCode = Arrays.hashCode((double[]) value);
+ }
+ else if (value instanceof byte[])
+ {
+ memberValueHashCode = Arrays.hashCode((byte[]) value);
+ }
+ else if (value instanceof char[])
+ {
+ memberValueHashCode = Arrays.hashCode((char[]) value);
+ }
+ else if (value instanceof Object[])
+ {
+ memberValueHashCode = Arrays.hashCode((Object[]) value);
+ }
+ else
+ {
+ memberValueHashCode = value.hashCode();
+ }
+ hashCode += memberNameHashCode ^ memberValueHashCode;
+ }
+ return hashCode;
+ }
+
+ private static Object invoke(Method method, Object instance)
+ {
+ try
+ {
+ if (!method.isAccessible())
+ method.setAccessible(true);
+ return method.invoke(instance);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new RuntimeException("Error checking value of member method "
+ + method.getName() + " on " + method.getDeclaringClass(), e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new RuntimeException("Error checking value of member method "
+ + method.getName() + " on " + method.getDeclaringClass(), e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new RuntimeException("Error checking value of member method "
+ + method.getName() + " on " + method.getDeclaringClass(), e);
+ }
+ }
+}
Modified: modules/trunk/remoting/src/main/java/org/jboss/seam/remoting/AnnotationsParser.java
===================================================================
--- modules/trunk/remoting/src/main/java/org/jboss/seam/remoting/AnnotationsParser.java 2009-12-01 07:00:40 UTC (rev 11707)
+++ modules/trunk/remoting/src/main/java/org/jboss/seam/remoting/AnnotationsParser.java 2009-12-01 10:53:56 UTC (rev 11708)
@@ -3,18 +3,26 @@
import java.io.StringReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.jboss.seam.remoting.annotationparser.AnnotationParser;
import org.jboss.seam.remoting.annotationparser.ParseException;
import org.jboss.seam.remoting.annotationparser.syntaxtree.AnnotationsUnit;
+import org.jboss.seam.remoting.annotationparser.syntaxtree.Literal;
import org.jboss.seam.remoting.annotationparser.syntaxtree.MarkerAnnotation;
+import org.jboss.seam.remoting.annotationparser.syntaxtree.MemberValue;
import org.jboss.seam.remoting.annotationparser.syntaxtree.MemberValuePair;
+import org.jboss.seam.remoting.annotationparser.syntaxtree.MemberValuePairs;
import org.jboss.seam.remoting.annotationparser.syntaxtree.Name;
import org.jboss.seam.remoting.annotationparser.syntaxtree.Node;
+import org.jboss.seam.remoting.annotationparser.syntaxtree.NodeChoice;
import org.jboss.seam.remoting.annotationparser.syntaxtree.NodeListOptional;
+import org.jboss.seam.remoting.annotationparser.syntaxtree.NodeOptional;
import org.jboss.seam.remoting.annotationparser.syntaxtree.NodeSequence;
import org.jboss.seam.remoting.annotationparser.syntaxtree.NodeToken;
import org.jboss.seam.remoting.annotationparser.syntaxtree.NormalAnnotation;
@@ -28,40 +36,42 @@
* @author Shane Bryzak
*/
public class AnnotationsParser extends DepthFirstVisitor
-{
- public enum AnnotationType { MARKER, SINGLE_MEMBER, NORMAL }
-
+{
protected class AnnotationMetadata
{
- private AnnotationType type;
- private String name;
+ private Class<? extends Annotation> annotationType;
+ private Map<String,Object> memberValues = new HashMap<String,Object>();
- public AnnotationMetadata(AnnotationType type, String name)
+ public AnnotationMetadata(String name)
{
- this.type = type;
- this.name = name;
+ this.annotationType = calcAnnotationType(name, beanType);
+ }
+
+ public void addMemberValue(String name, Object value)
+ {
+ memberValues.put(name, value);
}
- public AnnotationType getType()
+ public Map<String,Object> getMemberValues()
{
- return type;
+ return memberValues;
}
- public String getName()
+ public Class<? extends Annotation> getAnnotationType()
{
- return name;
+ return annotationType;
}
}
-
+
+ private Class<?> beanType;
private List<AnnotationMetadata> meta = new ArrayList<AnnotationMetadata>();
- private AnnotationMetadata currentAnnotation;
-
private Annotation[] annotations;
@SuppressWarnings("unchecked")
public AnnotationsParser(Class<?> beanType, String declaration)
{
+ this.beanType = beanType;
// TODO cache the results somewhere
AnnotationParser parser = new AnnotationParser(new StringReader(declaration));
@@ -82,12 +92,11 @@
for (int i = 0; i < meta.size(); i++)
{
AnnotationMetadata ann = meta.get(i);
- Class<?> annotationType = calcAnnotationType(ann.getName(), beanType);
InvocationHandler handler = new AnnotationInvocationHandler(
- (Class<? extends Annotation>) annotationType, null);
+ (Class<? extends Annotation>) ann.getAnnotationType(), ann.getMemberValues());
annotations[i] = (Annotation) Proxy.newProxyInstance(
- annotationType.getClassLoader(),
- new Class[] {annotationType}, handler);
+ ann.getAnnotationType().getClassLoader(),
+ new Class[] {ann.getAnnotationType()}, handler);
}
meta = null;
@@ -123,45 +132,146 @@
@Override
public void visit(AnnotationsUnit node)
{
+ List<org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation> annotations =
+ new ArrayList<org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation>();
+
+ NodeOptional n = (NodeOptional) node.f0;
+ if (n.present())
+ {
+ if (n.node instanceof NodeSequence)
+ {
+ NodeSequence ns = (NodeSequence) n.node;
+ {
+ for (Node nsNode : ns.nodes)
+ {
+ if (nsNode instanceof org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation)
+ {
+ annotations.add((org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation) nsNode);
+ }
+ else if (nsNode instanceof NodeListOptional)
+ {
+ NodeListOptional nlo = (NodeListOptional) nsNode;
+ if (nlo.present())
+ {
+ for (Node nloNode : nlo.nodes)
+ {
+ if (nloNode instanceof org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation)
+ {
+ annotations.add((org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation) nloNode);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation a : annotations)
+ {
+ processAnnotation(a);
+ }
+
super.visit(node);
}
- @Override
- public void visit(org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation node)
- {
- Node choice = node.f0.choice;
-
- AnnotationType type = null;
- Name name = null;
-
- if (choice instanceof MarkerAnnotation)
+ private void processAnnotation(org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation node)
+ {
+ if (node.f0.choice instanceof MarkerAnnotation)
{
- type = AnnotationType.MARKER;
- name = ((MarkerAnnotation) choice).f1;
+ meta.add(new AnnotationMetadata(extractName(((MarkerAnnotation) node.f0.choice).f1)));
}
- else if (choice instanceof NormalAnnotation)
+ else if (node.f0.choice instanceof NormalAnnotation)
{
- type = AnnotationType.NORMAL;
- name = ((NormalAnnotation) choice).f1;
+ NormalAnnotation ann = (NormalAnnotation) node.f0.choice;
+ AnnotationMetadata metadata = new AnnotationMetadata(extractName(ann.f1));
+
+ if (ann.f3.present() && ann.f3.node instanceof MemberValuePairs)
+ {
+ MemberValuePairs mvp = (MemberValuePairs) ann.f3.node;
+ extractMemberValue(metadata, mvp.f0.f0.tokenImage, mvp.f0.f2);
+
+ if (mvp.f1.present())
+ {
+ for (Node n : mvp.f1.nodes)
+ {
+ if (n instanceof MemberValuePair)
+ {
+ MemberValuePair p = (MemberValuePair) n;
+ extractMemberValue(metadata, p.f0.tokenImage, p.f2);
+ }
+ }
+ }
+ }
+ meta.add(metadata);
}
- else if (choice instanceof SingleMemberAnnotation)
+ else if (node.f0.choice instanceof SingleMemberAnnotation)
{
- type = AnnotationType.SINGLE_MEMBER;
- name = ((SingleMemberAnnotation) choice).f1;
+ AnnotationMetadata metadata = new AnnotationMetadata(
+ extractName(((SingleMemberAnnotation) node.f0.choice).f1));
+ extractMemberValue(metadata, "value", ((SingleMemberAnnotation) node.f0.choice).f3);
+ meta.add(metadata);
}
- currentAnnotation = new AnnotationMetadata(type, extractName(name));
- meta.add(currentAnnotation);
+ }
+
+ private void extractMemberValue(AnnotationMetadata metadata, String memberName,
+ MemberValue memberValue)
+ {
+ Class<?> memberType = null;
- super.visit(node);
+ for (Method m : metadata.getAnnotationType().getMethods())
+ {
+ if (memberName.equals(m.getName()))
+ {
+ memberType = m.getReturnType();
+ break;
+ }
+ }
+
+ if (memberType == null)
+ {
+ throw new RuntimeException("Annotation member " + memberName +
+ " not found on annotation type " + metadata.getAnnotationType().getName());
+ }
+
+ Object value = null;
+
+ switch (memberValue.f0.which)
+ {
+ // TODO add the missing conversions
+ case 0: // Annotation
+ break;
+ case 1: // MemberValueArray
+ break;
+ case 2: // Literal
+ value = convertLiteral((Literal) memberValue.f0.choice);
+ break;
+ }
+
+ metadata.addMemberValue(memberName, value);
}
- @Override
- public void visit(MemberValuePair node)
+ private Object convertLiteral(Literal literal)
{
+ // TODO add the missing conversions
+ switch (literal.f0.which)
+ {
+ case 0: // <INTEGER_LITERAL>
+ return Integer.parseInt(((NodeToken) literal.f0.choice).tokenImage);
+ case 1: // <FLOATING_POINT_LITERAL>
+ return Float.parseFloat(((NodeToken) literal.f0.choice).tokenImage);
+ case 2: // <CHARACTER_LITERAL>
+ case 3: // <STRING_LITERAL>
+ String value = ((NodeToken) literal.f0.choice).tokenImage;
+ return value.substring(1, value.length() - 1); // strip the double quotes
+ case 4: // BooleanLiteral()
+ case 5: // NullLiteral()
+ }
+ return null;
}
-
+
private String extractName(Name name)
{
StringBuilder sb = new StringBuilder();
More information about the seam-commits
mailing list