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.support;
018:
019: import java.io.Serializable;
020: import java.lang.reflect.Method;
021:
022: import org.springframework.aop.ClassFilter;
023: import org.springframework.aop.MethodMatcher;
024: import org.springframework.aop.Pointcut;
025: import org.springframework.core.ControlFlow;
026: import org.springframework.core.ControlFlowFactory;
027: import org.springframework.util.Assert;
028: import org.springframework.util.ObjectUtils;
029:
030: /**
031: * Pointcut and method matcher for use in simple <b>cflow</b>-style pointcut.
032: * Note that evaluating such pointcuts is 10-15 times slower than evaluating
033: * normal pointcuts, but they are useful in some cases.
034: *
035: * @author Rod Johnson
036: * @author Rob Harrop
037: * @see org.springframework.core.ControlFlow
038: */
039: public class ControlFlowPointcut implements Pointcut, ClassFilter,
040: MethodMatcher, Serializable {
041:
042: private Class clazz;
043:
044: private String methodName;
045:
046: private int evaluations;
047:
048: /**
049: * Construct a new pointcut that matches all control flows below that class.
050: * @param clazz the clazz
051: */
052: public ControlFlowPointcut(Class clazz) {
053: this (clazz, null);
054: }
055:
056: /**
057: * Construct a new pointcut that matches all calls below the
058: * given method in the given class. If the method name is null,
059: * matches all control flows below that class.
060: * @param clazz the clazz
061: * @param methodName the name of the method
062: */
063: public ControlFlowPointcut(Class clazz, String methodName) {
064: Assert.notNull(clazz, "Class must not be null");
065: this .clazz = clazz;
066: this .methodName = methodName;
067: }
068:
069: /**
070: * Subclasses can override this for greater filtering (and performance).
071: */
072: public boolean matches(Class clazz) {
073: return true;
074: }
075:
076: /**
077: * Subclasses can override this if it's possible to filter out
078: * some candidate classes.
079: */
080: public boolean matches(Method method, Class targetClass) {
081: return true;
082: }
083:
084: public boolean isRuntime() {
085: return true;
086: }
087:
088: public boolean matches(Method method, Class targetClass,
089: Object[] args) {
090: ++this .evaluations;
091: ControlFlow cflow = ControlFlowFactory.createControlFlow();
092: return (this .methodName != null) ? cflow.under(this .clazz,
093: this .methodName) : cflow.under(this .clazz);
094: }
095:
096: /**
097: * It's useful to know how many times we've fired, for optimization.
098: */
099: public int getEvaluations() {
100: return evaluations;
101: }
102:
103: public ClassFilter getClassFilter() {
104: return this ;
105: }
106:
107: public MethodMatcher getMethodMatcher() {
108: return this ;
109: }
110:
111: public boolean equals(Object other) {
112: if (this == other) {
113: return true;
114: }
115: if (!(other instanceof ControlFlowPointcut)) {
116: return false;
117: }
118: ControlFlowPointcut that = (ControlFlowPointcut) other;
119: return (this .clazz.equals(that.clazz))
120: && ObjectUtils.nullSafeEquals(that.methodName,
121: this .methodName);
122: }
123:
124: public int hashCode() {
125: int code = 17;
126: code = 37 * code + this .clazz.hashCode();
127: if (this .methodName != null) {
128: code = 37 * code + this.methodName.hashCode();
129: }
130: return code;
131: }
132:
133: }
|