~ubuntu-branches/ubuntu/natty/aspectj/natty

« back to all changes in this revision

Viewing changes to org.aspectj/modules/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java

  • Committer: Bazaar Package Importer
  • Author(s): Damien Raude-Morvan
  • Date: 2009-10-04 16:37:23 UTC
  • mfrom: (1.1.3 upstream) (3.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20091004163723-ck4y7j7fhjxskkie
Tags: 1.6.6+dfsg-1
* New upstream release.
  - Update 02_use_gjdoc.diff patch
* Update my email address

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* *******************************************************************
 
2
 * Copyright (c) 2004 IBM Corporation.
 
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
 * ******************************************************************/
 
10
package org.aspectj.weaver.patterns;
 
11
 
 
12
import java.io.DataOutputStream;
 
13
import java.io.IOException;
 
14
import java.util.ArrayList;
 
15
import java.util.Collections;
 
16
import java.util.List;
 
17
import java.util.Map;
 
18
 
 
19
import org.aspectj.bridge.IMessage;
 
20
import org.aspectj.bridge.MessageUtil;
 
21
import org.aspectj.util.FuzzyBoolean;
 
22
import org.aspectj.weaver.ISourceContext;
 
23
import org.aspectj.weaver.IntMap;
 
24
import org.aspectj.weaver.ResolvedType;
 
25
import org.aspectj.weaver.Shadow;
 
26
import org.aspectj.weaver.ShadowMunger;
 
27
import org.aspectj.weaver.UnresolvedType;
 
28
import org.aspectj.weaver.VersionedDataInputStream;
 
29
import org.aspectj.weaver.WeaverMessages;
 
30
import org.aspectj.weaver.World;
 
31
import org.aspectj.weaver.ast.Literal;
 
32
import org.aspectj.weaver.ast.Test;
 
33
import org.aspectj.weaver.ast.Var;
 
34
 
 
35
/**
 
36
 * @author colyer
 
37
 *
 
38
 * TODO To change the template for this generated type comment go to
 
39
 * Window - Preferences - Java - Code Style - Code Templates
 
40
 */
 
41
public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
 
42
 
 
43
        private boolean isThis;
 
44
        private boolean alreadyWarnedAboutDEoW = false;
 
45
        private ExactAnnotationTypePattern annotationTypePattern;
 
46
        private String declarationText;
 
47
        
 
48
        private static final int thisKindSet;
 
49
        private static final int targetKindSet;
 
50
        
 
51
        static {
 
52
                int thisFlags = Shadow.ALL_SHADOW_KINDS_BITS;
 
53
                int targFlags = Shadow.ALL_SHADOW_KINDS_BITS;
 
54
                for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
 
55
                        Shadow.Kind kind = Shadow.SHADOW_KINDS[i];
 
56
                        if (kind.neverHasThis()) thisFlags-=kind.bit;
 
57
                        if (kind.neverHasTarget()) targFlags-=kind.bit;
 
58
                }
 
59
                thisKindSet = thisFlags;
 
60
                targetKindSet=targFlags;
 
61
        }
 
62
        
 
63
        /**
 
64
         * 
 
65
         */
 
66
        public ThisOrTargetAnnotationPointcut(boolean isThis, ExactAnnotationTypePattern type) {
 
67
                super();
 
68
                this.isThis = isThis;
 
69
                this.annotationTypePattern = type;
 
70
                this.pointcutKind = ATTHIS_OR_TARGET;
 
71
                buildDeclarationText();
 
72
        }
 
73
 
 
74
        public ThisOrTargetAnnotationPointcut(boolean isThis, ExactAnnotationTypePattern type, ShadowMunger munger) {
 
75
            this(isThis,type);
 
76
        }
 
77
 
 
78
    public ExactAnnotationTypePattern getAnnotationTypePattern() {
 
79
        return annotationTypePattern;
 
80
    }
 
81
 
 
82
        public int couldMatchKinds() {
 
83
                return isThis ? thisKindSet : targetKindSet;
 
84
        }
 
85
        
 
86
        public Pointcut parameterizeWith(Map typeVariableMap,World w) {
 
87
                ExactAnnotationTypePattern newPattern = (ExactAnnotationTypePattern) this.annotationTypePattern.parameterizeWith(typeVariableMap,w);
 
88
                if (newPattern.getAnnotationType() instanceof ResolvedType) {
 
89
                        verifyRuntimeRetention(newPattern.getResolvedAnnotationType());
 
90
                }
 
91
                ThisOrTargetAnnotationPointcut ret = new ThisOrTargetAnnotationPointcut(isThis,(ExactAnnotationTypePattern)annotationTypePattern.parameterizeWith(typeVariableMap,w));
 
92
                ret.copyLocationFrom(this);
 
93
                return ret;
 
94
        }
 
95
        
 
96
        /* (non-Javadoc)
 
97
         * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
 
98
         */
 
99
        public FuzzyBoolean fastMatch(FastMatchInfo info) {
 
100
                return FuzzyBoolean.MAYBE;
 
101
        }
 
102
        
 
103
        /* (non-Javadoc)
 
104
         * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
 
105
         */
 
106
        protected FuzzyBoolean matchInternal(Shadow shadow) {
 
107
                if (!couldMatch(shadow)) return FuzzyBoolean.NO;
 
108
            ResolvedType toMatchAgainst = 
 
109
                (isThis ? shadow.getThisType() : shadow.getTargetType() ).resolve(shadow.getIWorld());
 
110
            annotationTypePattern.resolve(shadow.getIWorld());
 
111
            if (annotationTypePattern.matchesRuntimeType(toMatchAgainst).alwaysTrue()) {
 
112
                return FuzzyBoolean.YES;
 
113
            } else {
 
114
                // a subtype may match at runtime
 
115
                return FuzzyBoolean.MAYBE;
 
116
            }
 
117
        }
 
118
 
 
119
        public boolean isThis() { return isThis; }
 
120
        
 
121
        /* (non-Javadoc)
 
122
         * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings)
 
123
         */
 
124
        protected void resolveBindings(IScope scope, Bindings bindings) {
 
125
                if (!scope.getWorld().isInJava5Mode()) {
 
126
                        scope.message(MessageUtil.error(WeaverMessages.format(
 
127
                                        isThis ? WeaverMessages.ATTHIS_ONLY_SUPPORTED_AT_JAVA5_LEVEL : WeaverMessages.ATTARGET_ONLY_SUPPORTED_AT_JAVA5_LEVEL),
 
128
                                        getSourceLocation()));
 
129
                        return;
 
130
                }
 
131
                annotationTypePattern = (ExactAnnotationTypePattern) annotationTypePattern.resolveBindings(scope,bindings,true);
 
132
                // must be either a Var, or an annotation type pattern
 
133
                // if annotationType does not have runtime retention, this is an error
 
134
                if (annotationTypePattern.annotationType == null) {
 
135
                        // it's a formal with a binding error
 
136
                        return;
 
137
                }
 
138
                ResolvedType rAnnotationType = (ResolvedType) annotationTypePattern.annotationType;
 
139
                if (rAnnotationType.isTypeVariableReference()) return;  // we'll deal with this next check when the type var is actually bound...
 
140
                verifyRuntimeRetention(rAnnotationType);
 
141
                
 
142
        }
 
143
 
 
144
        private void verifyRuntimeRetention(ResolvedType rAnnotationType) {
 
145
                if (!(rAnnotationType.isAnnotationWithRuntimeRetention())) {
 
146
                    IMessage m = MessageUtil.error(
 
147
                                        WeaverMessages.format(WeaverMessages.BINDING_NON_RUNTIME_RETENTION_ANNOTATION,rAnnotationType.getName()),
 
148
                                        getSourceLocation());
 
149
                        rAnnotationType.getWorld().getMessageHandler().handleMessage(m);
 
150
                }
 
151
        }
 
152
 
 
153
        /* (non-Javadoc)
 
154
         * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedType, org.aspectj.weaver.IntMap)
 
155
         */
 
156
        protected Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
 
157
                if (isDeclare(bindings.getEnclosingAdvice())) {
 
158
                          // Enforce rule about which designators are supported in declare
 
159
                          if (!alreadyWarnedAboutDEoW) {
 
160
                                  inAspect.getWorld().showMessage(IMessage.ERROR,
 
161
                                                WeaverMessages.format(WeaverMessages.THIS_OR_TARGET_IN_DECLARE,isThis?"this":"target"),
 
162
                                                bindings.getEnclosingAdvice().getSourceLocation(), null);
 
163
                                  alreadyWarnedAboutDEoW = true;
 
164
                          }
 
165
                          return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
 
166
                }
 
167
 
 
168
                ExactAnnotationTypePattern newType = (ExactAnnotationTypePattern) annotationTypePattern.remapAdviceFormals(bindings);           
 
169
                ThisOrTargetAnnotationPointcut ret = 
 
170
                        new ThisOrTargetAnnotationPointcut(isThis, newType, bindings.getEnclosingAdvice());
 
171
                ret.alreadyWarnedAboutDEoW = alreadyWarnedAboutDEoW;
 
172
        ret.copyLocationFrom(this);
 
173
        return ret;
 
174
        }
 
175
 
 
176
        /* (non-Javadoc)
 
177
         * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
 
178
         */
 
179
        /**
 
180
         * The guard here is going to be the hasAnnotation() test - if it gets through (which we cannot determine until runtime) then
 
181
         * we must have a TypeAnnotationAccessVar in place - this means we must *always* have one in place.
 
182
         */
 
183
        protected Test findResidueInternal(Shadow shadow, ExposedState state) {
 
184
            if (!couldMatch(shadow)) return Literal.FALSE;
 
185
            boolean alwaysMatches = match(shadow).alwaysTrue();
 
186
            Var var = isThis ? shadow.getThisVar() : shadow.getTargetVar();
 
187
            Var annVar = null;
 
188
            
 
189
            // Are annotations being bound?
 
190
            UnresolvedType annotationType = annotationTypePattern.annotationType;
 
191
                if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
 
192
                        BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
 
193
                        annotationType = btp.annotationType;
 
194
                        
 
195
                        annVar = isThis ? shadow.getThisAnnotationVar(annotationType) :
 
196
                                shadow.getTargetAnnotationVar(annotationType);
 
197
                        if (annVar == null)
 
198
                                throw new RuntimeException("Impossible!");
 
199
 
 
200
                        state.set(btp.getFormalIndex(),annVar);
 
201
                }
 
202
 
 
203
                if (alwaysMatches && (annVar == null)) {//change check to verify if its the 'generic' annVar that is being used
 
204
                    return Literal.TRUE;
 
205
                } else {
 
206
                ResolvedType rType = annotationType.resolve(shadow.getIWorld());
 
207
                return Test.makeHasAnnotation(var,rType);
 
208
                }
 
209
        }
 
210
 
 
211
        
 
212
        private boolean couldMatch(Shadow shadow) {
 
213
                return isThis ? shadow.hasThis() : shadow.hasTarget();
 
214
        }
 
215
        
 
216
        
 
217
        /* (non-Javadoc)
 
218
         * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingAnnotationTypePatterns()
 
219
         */
 
220
        public List getBindingAnnotationTypePatterns() {
 
221
                if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
 
222
                        List l = new ArrayList();
 
223
                        l.add(annotationTypePattern);
 
224
                        return l;
 
225
                } else return Collections.EMPTY_LIST;
 
226
        }
 
227
        
 
228
        /* (non-Javadoc)
 
229
         * @see org.aspectj.weaver.patterns.NameBindingPointcut#getBindingTypePatterns()
 
230
         */
 
231
        public List getBindingTypePatterns() {
 
232
                return Collections.EMPTY_LIST;
 
233
        }
 
234
 
 
235
        /* (non-Javadoc)
 
236
         * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
 
237
         */
 
238
        public void write(DataOutputStream s) throws IOException {
 
239
            s.writeByte(Pointcut.ATTHIS_OR_TARGET);
 
240
            s.writeBoolean(isThis);
 
241
                annotationTypePattern.write(s);
 
242
                writeLocation(s);
 
243
        }
 
244
        
 
245
        public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
 
246
            boolean isThis = s.readBoolean();
 
247
                AnnotationTypePattern type = AnnotationTypePattern.read(s, context);
 
248
                ThisOrTargetAnnotationPointcut ret = new ThisOrTargetAnnotationPointcut(isThis,(ExactAnnotationTypePattern)type);
 
249
                ret.readLocation(context, s);
 
250
                return ret;
 
251
        }
 
252
        
 
253
        /* (non-Javadoc)
 
254
     * @see java.lang.Object#equals(java.lang.Object)
 
255
     */
 
256
    public boolean equals(Object obj) {
 
257
        if (!(obj instanceof ThisOrTargetAnnotationPointcut)) return false;
 
258
        ThisOrTargetAnnotationPointcut other = (ThisOrTargetAnnotationPointcut) obj;
 
259
        return ( other.annotationTypePattern.equals(this.annotationTypePattern) &&
 
260
                 (other.isThis == this.isThis) );
 
261
    }
 
262
    
 
263
    /* (non-Javadoc)
 
264
     * @see java.lang.Object#hashCode()
 
265
     */
 
266
    public int hashCode() {
 
267
        return 17 + 37*annotationTypePattern.hashCode() + (isThis ? 49 : 13);
 
268
    }
 
269
    
 
270
        /* (non-Javadoc)
 
271
     * @see java.lang.Object#toString()
 
272
     */
 
273
    private void buildDeclarationText() {
 
274
                StringBuffer buf = new StringBuffer();
 
275
                buf.append(isThis ? "@this(" : "@target(");
 
276
                String annPatt = annotationTypePattern.toString();
 
277
                buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt);
 
278
                buf.append(")");
 
279
                this.declarationText = buf.toString();   
 
280
        }
 
281
    
 
282
    public String toString() { return this.declarationText; }
 
283
 
 
284
    public Object accept(PatternNodeVisitor visitor, Object data) {
 
285
        return visitor.visit(this, data);
 
286
    }
 
287
}