001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.aop.aspectj;
018:
019: import org.aspectj.weaver.tools.PointcutParser;
020: import org.aspectj.weaver.tools.TypePatternMatcher;
021:
022: import org.springframework.aop.ClassFilter;
023: import org.springframework.util.Assert;
024: import org.springframework.util.StringUtils;
025:
026: /**
027: * Spring AOP {@link ClassFilter} implementation using AspectJ type matching.
028: *
029: * @author Rod Johnson
030: * @since 2.0
031: */
032: public class TypePatternClassFilter implements ClassFilter {
033:
034: private String typePattern;
035:
036: private TypePatternMatcher aspectJTypePatternMatcher;
037:
038: /**
039: * Creates a new instance of the {@link TypePatternClassFilter} class.
040: * <p>This is the JavaBean constructor; be sure to set the
041: * {@link #setTypePattern(String) typePattern} property, else a
042: * no doubt fatal {@link IllegalStateException} will be thrown
043: * when the {@link #matches(Class)} method is first invoked.
044: */
045: public TypePatternClassFilter() {
046: }
047:
048: /**
049: * Create a fully configured {@link TypePatternClassFilter} using the
050: * given type pattern.
051: * @param typePattern the type pattern that AspectJ weaver should parse
052: * @throws IllegalArgumentException if the supplied <code>typePattern</code> is <code>null</code>
053: * or is recognized as invalid
054: */
055: public TypePatternClassFilter(String typePattern) {
056: setTypePattern(typePattern);
057: }
058:
059: /**
060: * Set the AspectJ type pattern to match.
061: * <p>Examples include:
062: * <code class="code">
063: * org.springframework.beans.*
064: * </code>
065: * This will match any class or interface in the given package.
066: * <code class="code">
067: * org.springframework.beans.ITestBean+
068: * </code>
069: * This will match the <code>ITestBean</code> interface and any class
070: * that implements it.
071: * <p>These conventions are established by AspectJ, not Spring AOP.
072: * @param typePattern the type pattern that AspectJ weaver should parse
073: * @throws IllegalArgumentException if the supplied <code>typePattern</code> is <code>null</code>
074: * or is recognized as invalid
075: */
076: public void setTypePattern(String typePattern) {
077: Assert.notNull(typePattern);
078: this .typePattern = typePattern;
079: this .aspectJTypePatternMatcher = PointcutParser
080: .getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution()
081: .parseTypePattern(replaceBooleanOperators(typePattern));
082: }
083:
084: public String getTypePattern() {
085: return typePattern;
086: }
087:
088: /**
089: * Should the pointcut apply to the given interface or target class?
090: * @param clazz candidate target class
091: * @return whether the advice should apply to this candidate target class
092: * @throws IllegalStateException if no {@link #setTypePattern(String)} has been set
093: */
094: public boolean matches(Class clazz) {
095: if (this .aspectJTypePatternMatcher == null) {
096: throw new IllegalStateException(
097: "No 'typePattern' has been set via ctor/setter.");
098: }
099: return this .aspectJTypePatternMatcher.matches(clazz);
100: }
101:
102: /**
103: * If a type pattern has been specified in XML, the user cannot
104: * write <code>and</code> as "&&" (though && will work).
105: * We also allow <code>and</code> between two sub-expressions.
106: * <p>This method converts back to <code>&&</code> for the AspectJ pointcut parser.
107: */
108: private String replaceBooleanOperators(String pcExpr) {
109: pcExpr = StringUtils.replace(pcExpr, " and ", " && ");
110: pcExpr = StringUtils.replace(pcExpr, " or ", " || ");
111: pcExpr = StringUtils.replace(pcExpr, " not ", " ! ");
112: return pcExpr;
113: }
114: }
|