]> source.dussan.org Git - aspectj.git/blob
707f1e79eb944bd501ed3c1a3c12fb0de073b1c4
[aspectj.git] /
1 /* *******************************************************************
2  * Copyright (c) 2008 Contributors
3  * All rights reserved. 
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 
8  *  
9  * Contributors: 
10  *     Andy Clement     initial implementation 
11  * ******************************************************************/
12 package org.aspectj.weaver.patterns;
13
14 import java.io.IOException;
15 import java.util.Map;
16
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;
32
33 /**
34  * Represents an attempt to bind the field of an annotation within a pointcut. For example:<br>
35  * <code><pre>
36  * before(Level lev): execution(* *(..)) &amp;&amp; @annotation(TraceAnnotation(lev))
37  * </pre></code><br>
38  * This binding annotation type pattern will be for 'lev'.
39  */
40 public class BindingAnnotationFieldTypePattern extends ExactAnnotationTypePattern implements BindingPattern {
41
42         protected int formalIndex;
43         UnresolvedType formalType; // In this construct the formal type differs from the annotation type
44
45         public BindingAnnotationFieldTypePattern(UnresolvedType formalType, int formalIndex, UnresolvedType theAnnotationType) {
46                 super(theAnnotationType, null);
47                 this.formalIndex = formalIndex;
48                 this.formalType = formalType;
49         }
50
51         public void resolveBinding(World world) {
52                 if (resolved) {
53                         return;
54                 }
55                 resolved = true;
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()),
62                                                         getSourceLocation());
63                         world.getMessageHandler().handleMessage(m);
64                         resolved = false;
65                 }
66         }
67
68         @Override
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);
77                 // }
78                 // } else if (annotationType.isParameterizedType()) {
79                 // newAnnotationType = annotationType.parameterize(typeVariableMap);
80                 // }
81                 // BindingAnnotationTypePattern ret = new BindingAnnotationTypePattern(newAnnotationType, this.formalIndex);
82                 // if (newAnnotationType instanceof ResolvedType) {
83                 // ResolvedType rat = (ResolvedType) newAnnotationType;
84                 // verifyRuntimeRetention(rat.getWorld(), rat);
85                 // }
86                 // ret.copyLocationFrom(this);
87                 // return ret;
88         }
89
90         @Override
91         public int getFormalIndex() {
92                 return formalIndex;
93         }
94
95         @Override
96         public boolean equals(Object obj) {
97                 if (!(obj instanceof BindingAnnotationFieldTypePattern)) {
98                         return false;
99                 }
100                 BindingAnnotationFieldTypePattern btp = (BindingAnnotationFieldTypePattern) obj;
101                 return (btp.formalIndex == formalIndex) && (annotationType.equals(btp.annotationType))
102                                 && (formalType.equals(btp.formalType));
103         }
104
105         @Override
106         public int hashCode() {
107                 return (annotationType.hashCode() * 37 + formalIndex * 37) + formalType.hashCode();
108         }
109
110         @Override
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,
115                         // null);
116                 } else {
117                         int newFormalIndex = bindings.get(formalIndex);
118                         BindingAnnotationFieldTypePattern baftp = new BindingAnnotationFieldTypePattern(formalType, newFormalIndex,
119                                         annotationType);
120                         baftp.formalName = formalName;
121                         return baftp;
122                 }
123         }
124
125         @Override
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);
132                 writeLocation(s);
133         }
134
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);
139                 return ret;
140         }
141
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);
147                 return ret;
148         }
149
150         @Override
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;
157                 // }
158                 // }
159                 //
160                 if (annotated.hasAnnotation(annotationType)) {
161                         if (annotationType instanceof ReferenceType) {
162                                 ReferenceType rt = (ReferenceType) annotationType;
163                                 if (rt.getRetentionPolicy() != null && rt.getRetentionPolicy().equals("SOURCE")) {
164                                         rt.getWorld()
165                                                         .getMessageHandler()
166                                                         .handleMessage(
167                                                                         MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,
168                                                                                         annotationType, annotated), getSourceLocation()));
169                                         return FuzzyBoolean.NO;
170                                 }
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)) {
175                                                 found = true;
176                                         }
177                                 }
178                                 return (found ? FuzzyBoolean.YES : FuzzyBoolean.NO);
179                         }
180                 }
181                 // else if (checkSupers) {
182                 // ResolvedType toMatchAgainst = ((ResolvedType) annotated).getSuperclass();
183                 // while (toMatchAgainst != null) {
184                 // if (toMatchAgainst.hasAnnotation(annotationType)) {
185                 // return FuzzyBoolean.YES;
186                 // }
187                 // toMatchAgainst = toMatchAgainst.getSuperclass();
188                 // }
189                 // }
190                 //
191                 return FuzzyBoolean.NO;
192         }
193
194         public UnresolvedType getFormalType() {
195                 return formalType;
196         }
197
198 }