KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > compiler > crosscuts > joinpoints > JoinPoint


1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the compiler and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  *
22  * Contributor(s):
23  */

24
25 package org.aspectj.compiler.crosscuts.joinpoints;
26
27 import org.aspectj.compiler.base.ast.*;
28 import org.aspectj.compiler.base.*;
29 import org.aspectj.compiler.crosscuts.ast.*;
30 import org.aspectj.compiler.crosscuts.AspectJCompiler;
31 import org.aspectj.util.PartialOrder;
32
33 import java.util.*;
34
35 /**
36  * Each JoinPoint object is the static shadow of N possible dyanmic join points
37  * in the executing program. There should be exactly one JoinPoint object for each
38  * such possible static shadow.
39  */

40 public abstract class JoinPoint extends CompilerObject {
41     public final static int METHOD_EXECUTION = 0X001;
42     //public final static int METHOD_RECEPTION = 0x002;
43
public final static int METHOD_CALL = 0x004;
44     public final static int CONSTRUCTOR_EXECUTION = 0x008;
45     //public final static int CONSTRUCTOR_RECEPTION = 0x010;
46
public final static int CONSTRUCTOR_CALL = 0x020;
47     public final static int FIELD_GET = 0x040;
48     public final static int FIELD_SET = 0x080;
49     public final static int HANDLER = 0x100;
50
51     public final static int ADVICE_EXECUTION = 0x1000;
52     public final static int STATIC_INITIALIZER_EXECUTION = 0x2000;
53     public final static int INSTANCE_INITIALIZER_EXECUTION = 0x4000;
54     public final static int INITIALIZER_EXECUTION = 0x8000;
55
56     public final static int SUPER_METHOD_CALL = 0x10000;
57     public final static int SUPER_CONSTRUCTOR_CALL = 0x20000;
58
59     public static class Kind {
60         private String JavaDoc name;
61         private int id;
62
63         public Kind(String JavaDoc name, int id) {
64             this.name = name;
65             this.id = id;
66         }
67
68         public int getIntCode() {
69             return id;
70         }
71         public String JavaDoc toString() {
72             return name;
73         }
74         public String JavaDoc toFullString() {
75             return name;
76         }
77         public String JavaDoc toShortString() {
78             return name;
79         }
80     }
81
82     public abstract Kind getKind();
83
84     //initial size of 0 is a compromise optimization for a rarely used list
85
List plans /*JpPlan*/
86     = new ArrayList(0);
87     private boolean implementedPlans = false;
88
89     private VarDec dynamicJoinPointDec = null;
90     private FieldDec staticJoinPointDec = null;
91
92     public JoinPoint(JavaCompiler compiler) {
93         super(compiler);
94     }
95
96     public void addPlan(JpPlan plan) {
97         //System.out.println(this + " add " + plan);
98
plans.add(plan);
99     }
100
101     /*********************************************************************************
102      * get information about the join point
103      */

104     public abstract ASTObject getSourceLocation();
105
106     // This encapsulates the "signature" of the JoinPoint
107
public abstract Dec getTargetDec(); // { return getEnclosingCodeDec(); }
108
public SemanticObject getTargetSO() {
109         return getTargetDec().getCorrespondingSemanticObject();
110     }
111     // overridden only be CalleSideCallPoint
112
public ASTObject getTargetNode() {
113         return getSourceLocation();
114     }
115
116     // This is the "kind"
117
public final int getTypeCode() {
118         return getKind().getIntCode();
119     }
120
121     public abstract Type getResultType();
122
123     public Type getExceptionType() {
124         return null;
125     }
126
127     public Type getBytecodeType() {
128         return getSourceLocation().getBytecodeType();
129     }
130
131     public Type getDeclaringType() {
132         return getSourceLocation().getDeclaringType();
133     }
134
135     public abstract Type getTargetType();
136     
137     public Set getTargetTypes() {
138         Set ret = new HashSet();
139         Type t = getTargetType();
140         if (t == null) {
141             getCompiler().internalError("must override getTargetTypes in " + this);
142         } else {
143             ret.add(t);
144         }
145         return ret;
146     }
147
148     /**
149      * In the default case target == this
150      * @return the type of the target expr or null if there is no target
151      */

152     public Type getTargetExprType() {
153         return getThisExprType();
154     }
155
156     /**
157      * In the default case target == this
158      * @return a new expr that refers to the target or null if there is no target
159      */

160     public Expr makeTargetExpr() {
161         return makeThisExpr();
162     }
163
164     /**
165      * @return the type of the this expr or null if there is no this
166      */

167     public Type getThisExprType() {
168         if (isStaticContext())
169             return null;
170         else
171             return getDeclaringType();
172     }
173
174     public abstract boolean isStaticContext();
175
176     /**
177      * @return a new expr that refers to the target or null if there is no target
178      */

179     public Expr makeThisExpr() {
180         Type thisType = getThisExprType();
181         if (thisType == null)
182             return null;
183         else
184             return getAST().makeThis(thisType);
185     }
186
187     /**
188      * @return the Types of the args
189      */

190     // public List/*Type*/ getArgsTypes() {
191
// }
192

193     /**
194      * @return the args exprs
195      */

196     public abstract Exprs makeArgsExprs();
197
198     /* Used only by CalleeSideCallPoint XXX move it there */
199     public Expr makeThisExprOrType() {
200         if (isStaticContext()) {
201             return getAST().makeTypeExpr(getBytecodeType());
202         } else {
203             return getAST().makeThis(getBytecodeType());
204         }
205     }
206
207     public Expr makeVoidReturnExpr() {
208         return getAST().makeNull();
209     }
210
211     public abstract boolean canThrow(Type t);
212     public abstract Collection getPossibleCheckedExceptions();
213
214     public void showError(ASTObject node, String JavaDoc message) {
215         //XXX need to produce a crosscutting error here
216
node.showError("on target " + this +" " + message);
217         
218         if (plans.size() > 0) {
219             JpPlan plan = (JpPlan)plans.get(0);
220             if (plan instanceof AdvicePlan) {
221                 AdviceDec adviceDec = ((AdvicePlan)plan).getAdviceDec();
222                 if (adviceDec == node || adviceDec.getPcd() == node) {
223                     return;
224                 }
225                 ASTObject where = adviceDec.getPcd();
226                 where.showError("above target " + this + " is matched by");
227             }
228         }
229     }
230
231     public void showWarning(ASTObject node, String JavaDoc message) {
232         //XXX need to produce a crosscutting error here
233
node.showWarning("on target " + this +" " + message);
234     }
235
236     /*********************************************************************************
237      * get reflective exprs for run-time information about the join point
238      */

239     public Type makeFactoryType() {
240         return getTypeManager().getType("org.aspectj.runtime.reflect", "Factory");
241     }
242
243     public FieldDec makeFactoryDec() {
244         final AST ast = getAST();
245
246         java.io.File JavaDoc f = getStaticFieldHolder().getSourceFile();
247         String JavaDoc fname;
248         if (f == null)
249             fname = "<missing>";
250         else
251             fname = f.getName();
252
253         Modifiers modifiers = ast.makeModifiers(Modifiers.STATIC | Modifiers.FINAL);
254         if (getStaticFieldHolder().getType().isInterface())
255             modifiers.setPublic(true);
256
257         return ast.makeField(
258             modifiers,
259             makeFactoryType(),
260             "ajc$JPF",
261             ast.makeNew(
262                 makeFactoryType(),
263                 ast.makeLiteral(fname),
264                 ast.makeLiteral(getStaticFieldHolder().getType())));
265     }
266
267     public FieldDec getFactoryDec() {
268         if (getStaticFieldHolder().joinPointFactoryDec == null) {
269             FieldDec factoryDec = makeFactoryDec();
270             //factoryDec.setSynthetic();
271
getStaticFieldHolder().joinPointFactoryDec = factoryDec;
272             getStaticFieldHolder().getBody().add(0, factoryDec);
273         }
274         return getStaticFieldHolder().joinPointFactoryDec;
275     }
276
277     public Expr makeFactoryInstance() {
278         return getAST().makeGet(getFactoryDec());
279     }
280
281     public Expr makeObjectsArray(Formals formals) {
282         final AST ast = getAST();
283
284         Exprs exprs = ast.makeExprs();
285         for (int i = 0; i < formals.size(); i++) {
286             exprs.add(ast.makeVar(formals.get(i)));
287         }
288         return ast.makeObjectArray(exprs);
289     }
290
291     public String JavaDoc makeString(int i) {
292         return Integer.toString(i, 16);
293     }
294
295     public String JavaDoc makeString(Type t) {
296         return t.getExternalName();
297     }
298
299     public String JavaDoc makeString1(ASTObject ast, boolean asType) {
300         if (ast instanceof TypeD) {
301             return makeString(((TypeD) ast).getType());
302         } else if (ast instanceof FormalDec) {
303             FormalDec formal = (FormalDec) ast;
304             if (asType)
305                 return makeString(formal.getType());
306             else
307                 return formal.getId();
308         }
309         return "?";
310     }
311
312     public String JavaDoc makeString(TypeDs list) {
313         return makeString(list, true);
314     }
315
316     public String JavaDoc makeString(ASTObject list, boolean asType) {
317         if (list == null)
318             return "";
319         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
320         final int N = list.getChildCount();
321         for (int i = 0; i < N; i++) {
322             buf.append(makeString1(list.getChildAt(i), asType));
323             buf.append(':');
324         }
325         return buf.toString();
326     }
327
328     public Expr makeFactoryCall(String JavaDoc name, String JavaDoc stringRep) {
329         // return getAST().makeLiteral(stringRep);
330
return getAST().makeCall(
331             makeFactoryInstance(),
332             name,
333             getAST().makeLiteral(stringRep));
334     }
335
336     public Expr makeSignatureExpr(Dec dec) {
337         if (dec instanceof MethodDec) {
338             return makeSignatureExpr((MethodDec) dec);
339         } else if (dec instanceof ConstructorDec) {
340             return makeSignatureExpr((ConstructorDec) dec);
341         } else if (dec instanceof AdviceDec) {
342             return makeSignatureExpr((AdviceDec) dec);
343         } else if (dec instanceof FieldDec) {
344             return makeSignatureExpr((FieldDec) dec);
345         } else if (dec instanceof InitializerDec) {
346             return makeSignatureExpr((InitializerDec) dec);
347         } else {
348             return null;
349         }
350     }
351
352     public Expr makeSignatureExpr(ConstructorDec dec) {
353         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
354         buf.append(makeString(dec.getModifiers().getValue()));
355         buf.append('-');
356         buf.append('-');
357         buf.append(makeString(dec.getDeclaringType()));
358         buf.append('-');
359         buf.append(makeString(dec.getFormals(), true));
360         buf.append('-');
361         buf.append(makeString(dec.getFormals(), false));
362         buf.append('-');
363         buf.append(makeString(dec.getThrows()));
364         buf.append('-');
365         return makeFactoryCall("makeConstructorSig", buf.toString());
366     }
367
368     public Expr makeSignatureExpr(MethodDec dec) {
369         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
370         buf.append(makeString(dec.getModifiers().getValue()));
371         buf.append('-');
372         buf.append(dec.getName());
373         buf.append('-');
374         buf.append(makeString(dec.getDeclaringType()));
375         buf.append('-');
376         buf.append(makeString(dec.getFormals(), true));
377         buf.append('-');
378         buf.append(makeString(dec.getFormals(), false));
379         buf.append('-');
380         buf.append(makeString(dec.getThrows()));
381         buf.append('-');
382         buf.append(makeString(dec.getResultType()));
383         buf.append('-');
384         return makeFactoryCall("makeMethodSig", buf.toString());
385     }
386
387     public Expr makeSignatureExpr(AdviceDec dec) {
388         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
389         buf.append(makeString(dec.getModifiers().getValue()));
390         buf.append('-');
391         buf.append(dec.getName());
392         buf.append('-');
393         buf.append(makeString(dec.getDeclaringType()));
394         buf.append('-');
395         buf.append(makeString(dec.getFormals(), true));
396         buf.append('-');
397         buf.append(makeString(dec.getFormals(), false));
398         buf.append('-');
399         buf.append(makeString(dec.getThrows()));
400         buf.append('-');
401         buf.append(makeString(dec.getResultType()));
402         buf.append('-');
403         return makeFactoryCall("makeAdviceSig", buf.toString());
404     }
405
406     public Expr makeSignatureExpr(FieldDec dec) {
407         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
408         buf.append(makeString(dec.getModifiers().getValue()));
409         buf.append('-');
410         buf.append(dec.getName());
411         buf.append('-');
412         buf.append(makeString(dec.getDeclaringType()));
413         buf.append('-');
414         buf.append(makeString(dec.getType()));
415         buf.append('-');
416         return makeFactoryCall("makeFieldSig", buf.toString());
417     }
418
419     public Expr makeSignatureExpr(InitializerDec dec) {
420         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
421         buf.append(makeString(dec.getModifiers().getValue()));
422         buf.append('-');
423         buf.append('-');
424         buf.append(makeString(dec.getDeclaringType()));
425         buf.append('-');
426         return makeFactoryCall("makeInitializerSig", buf.toString());
427     }
428
429     public Expr makeSignatureExpr(CatchClause dec) {
430         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
431         buf.append('-');
432         buf.append('-');
433         buf.append(makeString(dec.getDeclaringType()));
434         buf.append('-');
435         buf.append(makeString(dec.getFormal().getType()));
436         buf.append('-');
437         buf.append(dec.getFormal().getId());
438         buf.append('-');
439         return makeFactoryCall("makeCatchClauseSig", buf.toString());
440     }
441
442     public Expr makeExecutingObjectExpr() {
443         Expr ret = makeThisExpr();
444         if (ret == null)
445             ret = getAST().makeNull();
446         return ret;
447     }
448
449     public JoinPoint getEnclosingExecutionJoinPoint() {
450         return null;
451     }
452
453     protected final Type getJoinPointType() {
454         return getTypeManager().getJoinPointType();
455     }
456
457     protected final Type getJoinPointStaticPartType() {
458         return getTypeManager().getJoinPointStaticPartType();
459     }
460
461     protected Expr makeSignatureExpr() {
462         return makeSignatureExpr(getTargetDec());
463     }
464     protected final String JavaDoc getKindString() {
465         return getKind().toFullString();
466     }
467
468     protected Expr makeStaticEnclosingExecutionJoinPointExpr() {
469         return null;
470     }
471
472     public final Expr makeStaticJoinPointExpr() {
473         final AST ast = getAST();
474
475         Exprs args =
476             ast.makeExprs(ast.makeLiteral(getKindString()), makeSignatureExpr());
477
478         ASTObject sourceLocation = getSourceLocation();
479         if (sourceLocation == null) {
480             args.add(ast.makeNull());
481         } else {
482             args.add(ast.makeLiteral(sourceLocation.getBeginLine()));
483             args.add(ast.makeLiteral(sourceLocation.getBeginColumn()));
484         }
485
486         return ast.makeCall(makeFactoryInstance(), "makeSJP", args);
487     }
488
489     private Expr reflectNull(Expr expr) {
490         if (expr == null)
491             return getAST().makeNull();
492         else
493             return expr;
494     }
495
496     public final Expr makeDynamicJoinPointExpr() {
497         final AST ast = getAST();
498
499         Exprs args =
500             ast.makeExprs(
501                 makeStaticJoinPointVarExpr(),
502                 reflectNull(makeThisExpr()),
503                 reflectNull(makeTargetExpr()),
504                 ast.makeObjectArray(makeArgsExprs()));
505         return ast.makeStaticCall(makeFactoryType(), "makeJP", args);
506     }
507
508     public Expr makeStaticEnclosingJoinPointVarExpr() {
509         if (getStaticEnclosingJoinPointDec() == null) {
510             return getAST().makeNull();
511         }
512         return getAST().makeGet(getStaticEnclosingJoinPointDec());
513     }
514
515     public Expr makeStaticJoinPointVarExpr() {
516         return getAST().makeGet(getStaticJoinPointDec());
517     }
518
519     public Expr makeDynamicJoinPointVarExpr() {
520         return getAST().makeVar(getDynamicJoinPointDec());
521     }
522
523     private boolean isSyntheticJoinPoint(Dec dec) {
524         if (dec.isSynthetic() && dec instanceof FieldDec) {
525             FieldDec field = (FieldDec) dec;
526             if (field.getId().indexOf("$ajcjp") != -1)
527                 return true;
528             if (field.getId().startsWith("ajc$"))
529                 return true;
530         }
531         return false;
532     }
533
534     public TypeDec getStaticFieldHolder() {
535         return getBytecodeType().getOutermostType().getTypeDec();
536     }
537
538     FieldDec makeStaticFinalField(Type type, String JavaDoc name, Expr value) {
539         final AST ast = getAST();
540         Modifiers modifiers =
541             ast.makeModifiers(Modifiers.FINAL | Modifiers.STATIC | Modifiers.PRIVATE);
542         if (getStaticFieldHolder().getType().isAspect())
543             modifiers.setPublic(true);
544         if (getStaticFieldHolder().getType().isInterface())
545             modifiers.setPublic(true);
546         FieldDec ret = ast.makeField(modifiers, type, name, value);
547         //ret.setSynthetic();
548
return ret;
549     }
550
551     void addStaticJoinPointDecToBody() {
552         if (staticJoinPointDec != null) {
553             staticJoinPointDec.setInitializer(makeStaticJoinPointExpr());
554             Decs body = getStaticFieldHolder().getBody();
555             int i = 0;
556             for (; i < body.size(); i++) {
557                 if (!isSyntheticJoinPoint(body.get(i))) {
558                     staticJoinPointDec.setId(staticJoinPointDec.getId() + i);
559                     body.add(i, staticJoinPointDec);
560                     break;
561                 }
562             }
563             if (i == body.size())
564                 body.add(staticJoinPointDec);
565         }
566     }
567
568     public FieldDec getStaticJoinPointDec() {
569         if (staticJoinPointDec == null) {
570             String JavaDoc name = getAST().makeGeneratedName(getTargetDec().getId() + "$ajcjp");
571             staticJoinPointDec =
572                 makeStaticFinalField(getJoinPointStaticPartType(), name, null);
573             staticJoinPointDec.setAllEnclosingTypes(getStaticFieldHolder().getType());
574         }
575         return staticJoinPointDec;
576     }
577
578     public VarDec getDynamicJoinPointDec() {
579         if (dynamicJoinPointDec == null) {
580             dynamicJoinPointDec =
581                 getAST().makeFinalVar(
582                     getJoinPointType(),
583                     "thisJoinPoint",
584                     makeDynamicJoinPointExpr());
585         }
586         return dynamicJoinPointDec;
587     }
588
589     public FieldDec getStaticEnclosingJoinPointDec() {
590         if (getEnclosingExecutionJoinPoint() == null) {
591             //System.out.println("no enclosing execution for: " + this);
592
return getStaticJoinPointDec();
593         }
594         return getEnclosingExecutionJoinPoint().getStaticJoinPointDec();
595     }
596
597     /**********************************************************************************/
598
599     //XXX this is the bare minimum for a useful error message here
600
void showPrettyCircularityError(List plans) {
601         for (Iterator i = plans.iterator(); i.hasNext();) {
602             AdvicePlan plan = (AdvicePlan) i.next();
603             AdviceDec adviceDec = plan.getAdviceDec();
604             AspectDec aspectDec = plan.getAspectDec();
605
606             if (adviceDec != null) {
607                 getCompiler().showError(
608                     adviceDec,
609                     "circularity in advice precedence applied to " + this);
610             } else {
611                 getCompiler().showError(
612                     null,
613                     plan + ": circularity in advice precedence applied to " + this);
614             }
615         }
616     }
617
618     public boolean hasPlans() {
619         return plans != null && plans.size() > 0;
620     }
621     
622     // only called from MethodCallJp.preImplement()
623
public boolean plansMatch(JoinPoint other) {
624         if (plans.size() != other.plans.size())
625             return false;
626
627         List otherPlans = new LinkedList(other.plans);
628
629         outer : for (Iterator i1 = plans.iterator(); i1.hasNext();) {
630             JpPlan plan1 = (JpPlan) i1.next();
631             // if one of the plans is for advice that needs call site context
632
// then we can't merge these sets
633
if (plan1 instanceof AdvicePlan) {
634                 AdvicePlan advicePlan = (AdvicePlan)plan1;
635                 if (advicePlan.getAdviceDec().needsCallSiteContext()) {
636                     return false;
637                 }
638             }
639             
640             for (Iterator i2 = otherPlans.iterator(); i2.hasNext();) {
641                 JpPlan plan2 = (JpPlan) i2.next();
642                 if (plan1.matches(plan2)) {
643                     i2.remove();
644                     continue outer;
645                 }
646             }
647             return false;
648         }
649         return true;
650     }
651
652     public void forgetPlans() {
653         plans = new ArrayList(0);
654     }
655
656     public void makeCorrespondences() {
657         if (plans == null)
658             return;
659
660         for (Iterator i = plans.iterator(); i.hasNext();) {
661             JpPlan plan = (JpPlan) i.next();
662             if (plan instanceof AdvicePlan) {
663                 AdviceDec adviceDec = ((AdvicePlan) plan).getAdviceDec();
664
665                 ASTObject codePoint = getTargetNode();
666
667                 // System.out.println("corr: " + adviceDec.toShortString() + " to "
668
// + codePoint.toShortString());
669
((AspectJCompiler) getCompiler()).getCorrespondences().addPointsTo(
670                     adviceDec,
671                     codePoint);
672             }
673         }
674     }
675
676     void sortPlans() {
677         if (plans.size() < 2)
678             return;
679
680         //??? could do this more efficiently by pre-sorting by kind,
681
//??? but we might remove that property from the language, so don't optimize yet.
682
if (PartialOrder.sort(plans) == null) {
683             showPrettyCircularityError(plans);
684         }
685     }
686     
687     public boolean needToImplement() {
688         return plans.size() != 0
689             || dynamicJoinPointDec != null
690             || staticJoinPointDec != null;
691     }
692
693     public void implementPlans() {
694         if (implementedPlans || !needToImplement()) return;
695         implementedPlans = true;
696         sortPlans();
697         Collections.reverse(plans);
698         getCompiler().showMessage(
699             " implementing plans on " + this +System.identityHashCode(this));
700
701         preImplement();
702         if (!needToImplement()) return;
703
704         for (Iterator i = plans.iterator(); i.hasNext();) {
705             JpPlan plan = (JpPlan) i.next();
706             plan.wrapJoinPoint(this);
707         }
708         makeCorrespondences();
709         finishJoinPoint();
710     }
711
712     protected void preImplement() {
713     }
714
715
716     public void finishJoinPoint() {
717         if (dynamicJoinPointDec != null) {
718             getStmts().add(0, dynamicJoinPointDec);
719         }
720
721         addStaticJoinPointDecToBody();
722     }
723
724     public abstract Stmts getStmts();
725
726     public abstract void setStmts(Stmts stmts);
727 }
Popular Tags