Переглянути джерело

annoValMatch: implementation

tags/V1_6_0M2
aclement 16 роки тому
джерело
коміт
b0a10381d5

+ 116
- 5
weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java Переглянути файл

@@ -11,15 +11,20 @@ package org.aspectj.weaver.patterns;

import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageUtil;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.AnnotatedElement;
import org.aspectj.weaver.AnnotationX;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.TypeVariableReference;
import org.aspectj.weaver.UnresolvedType;
@@ -37,11 +42,20 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
protected String formalName;
protected boolean resolved = false;
private boolean bindingPattern = false;
private Map annotationValues;
/**
* @param annotationValues
*
*/
public ExactAnnotationTypePattern(UnresolvedType annotationType) {
public ExactAnnotationTypePattern(UnresolvedType annotationType, Map annotationValues) {
this.annotationType = annotationType;
this.annotationValues = annotationValues;
this.resolved = (annotationType instanceof ResolvedType);
}
// Used when deserializing, values will be added
private ExactAnnotationTypePattern(UnresolvedType annotationType) {
this.annotationType = annotationType;
this.resolved = (annotationType instanceof ResolvedType);
}
@@ -61,9 +75,13 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
public UnresolvedType getAnnotationType() {
return annotationType;
}
public Map getAnnotationValues() {
return annotationValues;
}

public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
if (annotated.hasAnnotation(annotationType)) {
if (annotated.hasAnnotation(annotationType) && annotationValues == null) {
return FuzzyBoolean.YES;
} else {
// could be inherited, but we don't know that until we are
@@ -94,11 +112,73 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
return FuzzyBoolean.NO;
}
}
// Are we also matching annotation values?
if (annotationValues!=null) {
AnnotationX theAnnotation = annotated.getAnnotationOfType(annotationType);
// Check each one
Set keys = annotationValues.keySet();
for (Iterator keyIter = keys.iterator(); keyIter.hasNext();) {
String k = (String) keyIter.next();
String v = (String)annotationValues.get(k);
if (theAnnotation.hasNamedValue(k)) {
// Simple case, value is 'name=value' and the annotation specified the same thing
if (!theAnnotation.hasNameValuePair(k,v)) {
return FuzzyBoolean.NO;
}
} else {
// Complex case, look at the default value
ResolvedMember[] ms = ((ResolvedType)annotationType).getDeclaredMethods();
boolean foundMatch = false;
for (int i=0; i<ms.length && !foundMatch;i++) {
if (ms[i].isAbstract() && ms[i].getParameterTypes().length==0 && ms[i].getName().equals(k)) {
// we might be onto something
String s= ms[i].getAnnotationDefaultValue();
if (s!=null && s.equals(v)) foundMatch=true;;
}
}
if (!foundMatch)
return FuzzyBoolean.NO;
}
}
}
return FuzzyBoolean.YES;
} else if (checkSupers) {
ResolvedType toMatchAgainst = ((ResolvedType) annotated).getSuperclass();
while (toMatchAgainst != null) {
if (toMatchAgainst.hasAnnotation(annotationType)) {
// Are we also matching annotation values?
if (annotationValues!=null) {
AnnotationX theAnnotation = toMatchAgainst.getAnnotationOfType(annotationType);
// Check each one
Set keys = annotationValues.keySet();
for (Iterator keyIter = keys.iterator(); keyIter.hasNext();) {
String k = (String) keyIter.next();
String v = (String)annotationValues.get(k);
if (theAnnotation.hasNamedValue(k)) {
// Simple case, value is 'name=value' and the annotation specified the same thing
if (!theAnnotation.hasNameValuePair(k,v)) {
return FuzzyBoolean.NO;
}
} else {
// Complex case, look at the default value
ResolvedMember[] ms = ((ResolvedType)annotationType).getDeclaredMethods();
boolean foundMatch = false;
for (int i=0; i<ms.length && !foundMatch;i++) {
if (ms[i].isAbstract() && ms[i].getParameterTypes().length==0 && ms[i].getName().equals(k)) {
// we might be onto something
String s= ms[i].getAnnotationDefaultValue();
if (s!=null && s.equals(v)) foundMatch=true;;
}
}
if (!foundMatch)
return FuzzyBoolean.NO;
}
}
}
return FuzzyBoolean.YES;
}
toMatchAgainst = toMatchAgainst.getSuperclass();
@@ -109,6 +189,12 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
if (parameterAnnotations==null) return FuzzyBoolean.NO;
for (int i = 0; i < parameterAnnotations.length; i++) {
if (annotationType.equals(parameterAnnotations[i])) {
// Are we also matching annotation values?
if (annotationValues!=null) {
parameterAnnotations[i].getWorld().getMessageHandler().handleMessage(
MessageUtil.error("Compiler limitation: annotation value matching for parameter annotations not yet supported"));
return FuzzyBoolean.NO;
}
return FuzzyBoolean.YES;
}
}
@@ -132,7 +218,9 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {

public void resolve(World world) {
if (!resolved) annotationType = annotationType.resolve(world);
if (!resolved) {
annotationType = annotationType.resolve(world);
}
resolved = true;
}

@@ -199,7 +287,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
} else if (annotationType.isParameterizedType()) {
newAnnotationType = annotationType.parameterize(typeVariableMap);
}
ExactAnnotationTypePattern ret = new ExactAnnotationTypePattern(newAnnotationType);
ExactAnnotationTypePattern ret = new ExactAnnotationTypePattern(newAnnotationType,annotationValues);
ret.formalName = formalName;
ret.bindingPattern = bindingPattern;
ret.copyLocationFrom(this);
@@ -241,10 +329,21 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
}
writeLocation(s);
s.writeBoolean(isForParameterAnnotationMatch());
if (annotationValues==null) {
s.writeInt(0);
} else {
s.writeInt(annotationValues.size());
Set key = annotationValues.keySet();
for (Iterator keys = key.iterator(); keys.hasNext();) {
String k = (String) keys.next();
s.writeUTF(k);
s.writeUTF((String)annotationValues.get(k));
}
}
}

public static AnnotationTypePattern read(VersionedDataInputStream s,ISourceContext context) throws IOException {
AnnotationTypePattern ret;
ExactAnnotationTypePattern ret;
byte version = s.readByte();
if (version > VERSION) {
throw new BCException("ExactAnnotationTypePattern was written by a newer version of AspectJ");
@@ -259,6 +358,18 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160) {
if (s.readBoolean()) ret.setForParameterAnnotationMatch();
}
if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160M2) {
int annotationValueCount = s.readInt();
if (annotationValueCount>0) {
Map aValues = new HashMap();
for (int i=0;i<annotationValueCount;i++) {
String key = s.readUTF();
String val = s.readUTF();
aValues.put(key,val);
}
ret.annotationValues = aValues;
}
}
return ret;
}

+ 184
- 3
weaver/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java Переглянути файл

@@ -11,7 +11,10 @@ package org.aspectj.weaver.patterns;

import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.MessageUtil;
@@ -19,6 +22,7 @@ import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.AnnotatedElement;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.WeaverMessages;
@@ -35,6 +39,7 @@ public class WildAnnotationTypePattern extends AnnotationTypePattern {

private TypePattern typePattern;
private boolean resolved = false;
Map annotationValues;
/**
*
@@ -44,11 +49,19 @@ public class WildAnnotationTypePattern extends AnnotationTypePattern {
this.typePattern = typePattern;
this.setLocation(typePattern.getSourceContext(), typePattern.start, typePattern.end);
}
public WildAnnotationTypePattern(TypePattern typePattern, Map annotationValues) {
super();
this.typePattern = typePattern;
this.annotationValues = annotationValues;
// PVAL make the location be from start of type pattern to end of values
this.setLocation(typePattern.getSourceContext(), typePattern.start, typePattern.end);
}

public TypePattern getTypePattern() {
return typePattern;
}

/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.AnnotationTypePattern#matches(org.aspectj.weaver.AnnotatedElement)
*/
@@ -56,10 +69,152 @@ public class WildAnnotationTypePattern extends AnnotationTypePattern {
return matches(annotated,null);
}

/**
* Resolve any annotation values specified, checking they are all well formed (valid names, valid values)
* @param annotationType the annotation type for which the values have been specified
* @param scope the scope within which to resolve type references (eg. Color.GREEN)
*/
protected void resolveAnnotationValues(ResolvedType annotationType, IScope scope) {
if (annotationValues == null) return;
// Check any values specified are OK:
// - the value names are for valid annotation fields
// - the specified values are of the correct type
// - for enums, check the specified values can be resolved in the specified scope
Set keys = annotationValues.keySet();
ResolvedMember[] ms = annotationType.getDeclaredMethods();
for (Iterator kIter = keys.iterator(); kIter.hasNext();) {
String k = (String) kIter.next();
String v = (String) annotationValues.get(k);
boolean validKey = false;
for (int i = 0; i < ms.length; i++) {
ResolvedMember resolvedMember = ms[i];
if (resolvedMember.getName().equals(k) && resolvedMember.isAbstract()) {
validKey = true;
ResolvedType t = resolvedMember.getReturnType().resolve(scope.getWorld());
if (t.isEnum()) {
// value must be an enum reference X.Y
int pos = v.lastIndexOf(".");
if (pos == -1) {
IMessage m = MessageUtil.error(
WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"enum"),
getSourceLocation());
scope.getWorld().getMessageHandler().handleMessage(m);
} else {
String typename = v.substring(0,pos);
ResolvedType rt = scope.lookupType(typename, this).resolve(scope.getWorld());
v = rt.getSignature()+v.substring(pos+1); // from 'Color.RED' to 'Lp/Color;RED'
annotationValues.put(k,v);
}
} else if (t.isPrimitiveType()) {
if (t.getSignature()=="I") {
try {
Integer value = Integer.parseInt(v);
annotationValues.put(k,value.toString());
} catch (NumberFormatException nfe) {
IMessage m = MessageUtil.error(
WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"int"),
getSourceLocation());
scope.getWorld().getMessageHandler().handleMessage(m);
}
} else if (t.getSignature()=="F") {
try {
Float value = Float.parseFloat(v);
annotationValues.put(k,value.toString());
} catch (NumberFormatException nfe) {
IMessage m = MessageUtil.error(
WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"float"),
getSourceLocation());
scope.getWorld().getMessageHandler().handleMessage(m);
}

} else if (t.getSignature()=="Z") {
if (v.equalsIgnoreCase("true") || v.equalsIgnoreCase("false")) {
// is it ok !
} else {
IMessage m = MessageUtil.error(
WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"boolean"),
getSourceLocation());
scope.getWorld().getMessageHandler().handleMessage(m);
}
} else if (t.getSignature()=="S") {
try {
Short value = Short.parseShort(v);
annotationValues.put(k,value.toString());
} catch (NumberFormatException nfe) {
IMessage m = MessageUtil.error(
WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"short"),
getSourceLocation());
scope.getWorld().getMessageHandler().handleMessage(m);
}
} else if (t.getSignature()=="J") {
try {
Long value = Long.parseLong(v);
annotationValues.put(k,value.toString());
} catch (NumberFormatException nfe) {
IMessage m = MessageUtil.error(
WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"long"),
getSourceLocation());
scope.getWorld().getMessageHandler().handleMessage(m);
}
} else if (t.getSignature()=="D") {
try {
Double value = Double.parseDouble(v);
annotationValues.put(k,value.toString());
} catch (NumberFormatException nfe) {
IMessage m = MessageUtil.error(
WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"double"),
getSourceLocation());
scope.getWorld().getMessageHandler().handleMessage(m);
}
} else if (t.getSignature()=="B") {
try {
Byte value = Byte.parseByte(v);
annotationValues.put(k,value.toString());
} catch (NumberFormatException nfe) {
IMessage m = MessageUtil.error(
WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"byte"),
getSourceLocation());
scope.getWorld().getMessageHandler().handleMessage(m);
}
} else if (t.getSignature()=="C") {
if (v.length()!=3) { // '?'
IMessage m = MessageUtil.error(
WeaverMessages.format(WeaverMessages.INVALID_ANNOTATION_VALUE,v,"char"),
getSourceLocation());
scope.getWorld().getMessageHandler().handleMessage(m);
} else {
annotationValues.put(k,v.substring(1,2));
}
} else {
throw new RuntimeException("Not implemented for "+t);
}
} else if (t.equals(ResolvedType.JAVA_LANG_STRING)) {
// nothing to do, it will be OK
} else {
throw new RuntimeException("Compiler limitation: annotation value support not implemented for type "+t);
}
}
}
if (!validKey) {
IMessage m = MessageUtil.error(
WeaverMessages.format(WeaverMessages.UNKNOWN_ANNOTATION_VALUE,annotationType,k),
getSourceLocation());
scope.getWorld().getMessageHandler().handleMessage(m);
}
}
}




public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
if (!resolved) {
throw new IllegalStateException("Can't match on an unresolved annotation type pattern");
}
if (annotationValues!=null) {
// PVAL improve this restriction, would allow '*(value=Color.RED)'
throw new IllegalStateException("Cannot use annotationvalues with a wild annotation pattern");
}
if (isForParameterAnnotationMatch()) {
if (parameterAnnotations!=null && parameterAnnotations.length!=0) {
for (int i = 0; i < parameterAnnotations.length; i++) {
@@ -114,7 +269,9 @@ public class WildAnnotationTypePattern extends AnnotationTypePattern {
scope.getWorld().getMessageHandler().handleMessage(m);
resolved = false;
}
ExactAnnotationTypePattern eatp = new ExactAnnotationTypePattern(et.getExactType().resolve(scope.getWorld()));
ResolvedType annotationType = et.getExactType().resolve(scope.getWorld());
resolveAnnotationValues(annotationType,scope);
ExactAnnotationTypePattern eatp = new ExactAnnotationTypePattern(annotationType,annotationValues);
eatp.copyLocationFrom(this);
if (isForParameterAnnotationMatch()) eatp.setForParameterAnnotationMatch();
return eatp;
@@ -140,10 +297,22 @@ public class WildAnnotationTypePattern extends AnnotationTypePattern {
typePattern.write(s);
writeLocation(s);
s.writeBoolean(isForParameterAnnotationMatch());
// PVAL
if (annotationValues==null) {
s.writeInt(0);
} else {
s.writeInt(annotationValues.size());
Set key = annotationValues.keySet();
for (Iterator keys = key.iterator(); keys.hasNext();) {
String k = (String) keys.next();
s.writeUTF(k);
s.writeUTF((String)annotationValues.get(k));
}
}
}

public static AnnotationTypePattern read(VersionedDataInputStream s,ISourceContext context) throws IOException {
AnnotationTypePattern ret;
WildAnnotationTypePattern ret;
byte version = s.readByte();
if (version > VERSION) {
throw new BCException("ExactAnnotationTypePattern was written by a newer version of AspectJ");
@@ -154,6 +323,18 @@ public class WildAnnotationTypePattern extends AnnotationTypePattern {
if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MINOR_AJ160) {
if (s.readBoolean()) ret.setForParameterAnnotationMatch();
}
if (s.getMajorVersion()>=WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ160M2) {
int annotationValueCount = s.readInt();
if (annotationValueCount>0) {
Map aValues = new HashMap();
for (int i=0;i<annotationValueCount;i++) {
String key = s.readUTF();
String val = s.readUTF();
aValues.put(key,val);
}
ret.annotationValues = aValues;
}
}
return ret;
}


Завантаження…
Відмінити
Зберегти