KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > aop > aspectj > annotation > AspectMetadata


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.aop.aspectj.annotation;
18
19 import org.aspectj.lang.annotation.Aspect;
20 import org.aspectj.lang.reflect.AjType;
21 import org.aspectj.lang.reflect.AjTypeSystem;
22 import org.aspectj.lang.reflect.PerClauseKind;
23
24 import org.springframework.aop.Pointcut;
25 import org.springframework.aop.aspectj.AspectJExpressionPointcut;
26 import org.springframework.aop.aspectj.TypePatternClassFilter;
27 import org.springframework.aop.framework.AopConfigException;
28 import org.springframework.aop.support.ComposablePointcut;
29
30 /**
31  * Metadata for an AspectJ aspect class, with an additional Spring AOP pointcut
32  * for the per clause.
33  *
34  * <p>Uses AspectJ 5 AJType reflection API, so is only supported on Java 5.
35  * Enables us to work with different AspectJ instantiation models such as
36  * "singleton", "pertarget" and "perthis".
37  *
38  * @author Rod Johnson
39  * @author Juergen Hoeller
40  * @since 2.0
41  * @see org.springframework.aop.aspectj.AspectJExpressionPointcut
42  */

43 public class AspectMetadata {
44
45     /**
46      * AspectJ reflection information (AspectJ 5 / Java 5 specific).
47      */

48     private final AjType ajType;
49
50     /**
51      * Spring AOP pointcut corresponding to the per clause of the
52      * aspect. Will be the Pointcut.TRUE canonical instance in the
53      * case of a singleton, otherwise an AspectJExpressionPointcut.
54      */

55     private final Pointcut perClausePointcut;
56
57     /**
58      * The name of this aspect as defined to Spring (the bean name) -
59      * allows us to determine if two pieces of advice come from the
60      * same aspect and hence their relative precedence.
61      */

62     private String JavaDoc aspectName;
63
64
65     /**
66      * Create a new AspectMetadata instance for the given aspect class.
67      * @param aspectClass the aspect class
68      * @param aspectName the name of the aspect
69      */

70     public AspectMetadata(Class JavaDoc aspectClass, String JavaDoc aspectName) {
71         this.aspectName = aspectName;
72         this.ajType = AjTypeSystem.getAjType(aspectClass);
73         
74         if (!this.ajType.isAspect()) {
75             throw new IllegalArgumentException JavaDoc("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
76         }
77         if (this.ajType.getDeclarePrecedence().length > 0) {
78             throw new IllegalArgumentException JavaDoc("DeclarePrecendence not presently supported in Spring AOP");
79         }
80
81         switch (this.ajType.getPerClause().getKind()) {
82             case SINGLETON :
83                 this.perClausePointcut = Pointcut.TRUE;
84                 return;
85             case PERTARGET : case PERTHIS :
86                 AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
87                 ajexp.setLocation("@Aspect annotation on " + aspectClass.getName());
88                 ajexp.setExpression(findPerClause(aspectClass));
89                 this.perClausePointcut = ajexp;
90                 return;
91             case PERTYPEWITHIN :
92                 // Works with a type pattern
93
this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(findPerClause(aspectClass)));
94                 return;
95             default :
96                 throw new AopConfigException(
97                         "PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
98         }
99     }
100
101     /**
102      * Extract contents from String of form <code>pertarget(contents)</code>.
103      */

104     private String JavaDoc findPerClause(Class JavaDoc<?> aspectClass) {
105         // TODO when AspectJ provides this, we can remove this hack. Hence we don't
106
// bother to make it elegant. Or efficient. Or robust :-)
107
String JavaDoc str = aspectClass.getAnnotation(Aspect.class).value();
108         str = str.substring(str.indexOf("(") + 1);
109         str = str.substring(0, str.length() - 1);
110         return str;
111     }
112
113
114     /**
115      * Return AspectJ reflection information.
116      */

117     public AjType getAjType() {
118         return this.ajType;
119     }
120
121     /**
122      * Return the aspect class.
123      */

124     public Class JavaDoc getAspectClass() {
125         return this.ajType.getJavaClass();
126     }
127
128     /**
129      * Return the aspect class.
130      */

131     public String JavaDoc getAspectName() {
132         return this.aspectName;
133     }
134
135     /**
136      * Return a Spring pointcut expression for a singleton aspect.
137      * (e.g. <code>Pointcut.TRUE</code> if it's a singleton).
138      */

139     public Pointcut getPerClausePointcut() {
140         return this.perClausePointcut;
141     }
142
143     /**
144      * Return whether the aspect is defined as "perthis" or "pertarget".
145      */

146     public boolean isPerThisOrPerTarget() {
147         PerClauseKind kind = getAjType().getPerClause().getKind();
148         return (kind == PerClauseKind.PERTARGET || kind == PerClauseKind.PERTHIS);
149     }
150
151     /**
152      * Return whether the aspect is defined as "pertypewithin".
153      */

154     public boolean isPerTypeWithin() {
155         PerClauseKind kind = getAjType().getPerClause().getKind();
156         return (kind == PerClauseKind.PERTYPEWITHIN);
157     }
158
159     /**
160      * Return whether the aspect needs to be lazily instantiated.
161      */

162     public boolean isLazilyInstantiated() {
163         return (isPerThisOrPerTarget() || isPerTypeWithin());
164     }
165
166 }
167
Popular Tags