1 /* *******************************************************************
2 * Copyright (c) 2008 Contributors
4 * This program and the accompanying materials are made available
5 * under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Andy Clement initial implementation
11 * ******************************************************************/
12 package org.aspectj.weaver.patterns;
14 import java.io.IOException;
17 import org.aspectj.bridge.IMessage;
18 import org.aspectj.bridge.MessageUtil;
19 import org.aspectj.util.FuzzyBoolean;
20 import org.aspectj.weaver.AnnotatedElement;
21 import org.aspectj.weaver.BCException;
22 import org.aspectj.weaver.CompressingDataOutputStream;
23 import org.aspectj.weaver.ISourceContext;
24 import org.aspectj.weaver.IntMap;
25 import org.aspectj.weaver.ReferenceType;
26 import org.aspectj.weaver.ResolvedMember;
27 import org.aspectj.weaver.ResolvedType;
28 import org.aspectj.weaver.UnresolvedType;
29 import org.aspectj.weaver.VersionedDataInputStream;
30 import org.aspectj.weaver.WeaverMessages;
31 import org.aspectj.weaver.World;
34 * Represents an attempt to bind the field of an annotation within a pointcut. For example:<br>
36 * before(Level lev): execution(* *(..)) && @annotation(TraceAnnotation(lev))
38 * This binding annotation type pattern will be for 'lev'.
40 public class BindingAnnotationFieldTypePattern extends ExactAnnotationTypePattern implements BindingPattern {
42 protected int formalIndex;
43 UnresolvedType formalType; // In this construct the formal type differs from the annotation type
45 public BindingAnnotationFieldTypePattern(UnresolvedType formalType, int formalIndex, UnresolvedType theAnnotationType) {
46 super(theAnnotationType, null);
47 this.formalIndex = formalIndex;
48 this.formalType = formalType;
51 public void resolveBinding(World world) {
56 formalType = world.resolve(formalType);
57 annotationType = world.resolve(annotationType);
58 ResolvedType annoType = (ResolvedType) annotationType;
59 if (!annoType.isAnnotation()) {
60 IMessage m = MessageUtil
61 .error(WeaverMessages.format(WeaverMessages.REFERENCE_TO_NON_ANNOTATION_TYPE, annoType.getName()),
63 world.getMessageHandler().handleMessage(m);
69 public AnnotationTypePattern parameterizeWith(Map typeVariableMap, World w) {
70 throw new BCException("Parameterization not implemented for annotation field binding construct (compiler limitation)");
71 // UnresolvedType newAnnotationType = annotationType;
72 // if (annotationType.isTypeVariableReference()) {
73 // TypeVariableReference t = (TypeVariableReference) annotationType;
74 // String key = t.getTypeVariable().getName();
75 // if (typeVariableMap.containsKey(key)) {
76 // newAnnotationType = (UnresolvedType) typeVariableMap.get(key);
78 // } else if (annotationType.isParameterizedType()) {
79 // newAnnotationType = annotationType.parameterize(typeVariableMap);
81 // BindingAnnotationTypePattern ret = new BindingAnnotationTypePattern(newAnnotationType, this.formalIndex);
82 // if (newAnnotationType instanceof ResolvedType) {
83 // ResolvedType rat = (ResolvedType) newAnnotationType;
84 // verifyRuntimeRetention(rat.getWorld(), rat);
86 // ret.copyLocationFrom(this);
91 public int getFormalIndex() {
96 public boolean equals(Object obj) {
97 if (!(obj instanceof BindingAnnotationFieldTypePattern)) {
100 BindingAnnotationFieldTypePattern btp = (BindingAnnotationFieldTypePattern) obj;
101 return (btp.formalIndex == formalIndex) && (annotationType.equals(btp.annotationType))
102 && (formalType.equals(btp.formalType));
106 public int hashCode() {
107 return (annotationType.hashCode() * 37 + formalIndex * 37) + formalType.hashCode();
111 public AnnotationTypePattern remapAdviceFormals(IntMap bindings) {
112 if (!bindings.hasKey(formalIndex)) {
113 throw new BCException("Annotation field binding reference must be bound (compiler limitation)");
114 // must be something like returning the unbound form: return new ExactAnnotationTypePattern(annotationType,
117 int newFormalIndex = bindings.get(formalIndex);
118 BindingAnnotationFieldTypePattern baftp = new BindingAnnotationFieldTypePattern(formalType, newFormalIndex,
120 baftp.formalName = formalName;
126 public void write(CompressingDataOutputStream s) throws IOException {
127 s.writeByte(AnnotationTypePattern.BINDINGFIELD2);
128 formalType.write(s); // the type of the field within the annotation
129 s.writeShort((short) formalIndex);
130 annotationType.write(s); // the annotation type
131 s.writeUTF(formalName);
135 public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
136 AnnotationTypePattern ret = new BindingAnnotationFieldTypePattern(UnresolvedType.read(s), s.readShort(),
137 UnresolvedType.read(s));
138 ret.readLocation(context, s);
142 public static AnnotationTypePattern read2(VersionedDataInputStream s, ISourceContext context) throws IOException {
143 BindingAnnotationFieldTypePattern ret = new BindingAnnotationFieldTypePattern(UnresolvedType.read(s), s.readShort(),
144 UnresolvedType.read(s));
145 ret.formalName = s.readUTF();
146 ret.readLocation(context, s);
151 public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations) {
152 // Inheritance irrelevant because @annotation(Anno(x)) only supported at method execution join points (compiler limitation)
153 // boolean checkSupers = false;
154 // if (getResolvedAnnotationType().hasAnnotation(UnresolvedType.AT_INHERITED)) {
155 // if (annotated instanceof ResolvedType) {
156 // checkSupers = true;
160 if (annotated.hasAnnotation(annotationType)) {
161 if (annotationType instanceof ReferenceType) {
162 ReferenceType rt = (ReferenceType) annotationType;
163 if (rt.getRetentionPolicy() != null && rt.getRetentionPolicy().equals("SOURCE")) {
167 MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,
168 annotationType, annotated), getSourceLocation()));
169 return FuzzyBoolean.NO;
171 ResolvedMember[] methods = rt.getDeclaredMethods();
172 boolean found = false;
173 for (int i = 0; i < methods.length && !found; i++) {
174 if (methods[i].getReturnType().equals(formalType)) {
178 return (found ? FuzzyBoolean.YES : FuzzyBoolean.NO);
181 // else if (checkSupers) {
182 // ResolvedType toMatchAgainst = ((ResolvedType) annotated).getSuperclass();
183 // while (toMatchAgainst != null) {
184 // if (toMatchAgainst.hasAnnotation(annotationType)) {
185 // return FuzzyBoolean.YES;
187 // toMatchAgainst = toMatchAgainst.getSuperclass();
191 return FuzzyBoolean.NO;
194 public UnresolvedType getFormalType() {