001package org.javasimon.spring;
002
003import java.lang.reflect.Method;
004
005import org.javasimon.aop.Monitored;
006
007import org.springframework.aop.ClassFilter;
008import org.springframework.aop.MethodMatcher;
009import org.springframework.aop.Pointcut;
010import org.springframework.aop.support.AopUtils;
011import org.springframework.core.annotation.AnnotationUtils;
012import org.springframework.util.ClassUtils;
013
014/**
015 * Pointcut that identifies methods/classes with the {@link Monitored} annotation.
016 *
017 * @author Erik van Oosten
018 * @author <a href="mailto:virgo47@gmail.com">Richard "Virgo" Richter</a>
019 */
020public final class MonitoredMeasuringPointcut implements Pointcut {
021        /**
022         * Returns a class filter that lets all class through.
023         *
024         * @return a class filter that lets all class through
025         */
026        @Override
027        public ClassFilter getClassFilter() {
028                return ClassFilter.TRUE;
029        }
030
031        /**
032         * Returns a method matcher that matches any method that has the {@link Monitored} annotation,
033         * or is in a class with the {@link Monitored} annotation or is in a subclass of such a class or interface.
034         *
035         * @return method matcher matching {@link Monitored} methods
036         */
037        @Override
038        public MethodMatcher getMethodMatcher() {
039                return MonitoredMethodMatcher.INSTANCE;
040        }
041
042        private enum MonitoredMethodMatcher implements MethodMatcher {
043                INSTANCE;
044
045                @Override
046                public boolean matches(Method method, Class targetClass) {
047                        return !ClassUtils.isCglibProxyClass(targetClass) && isMonitoredAnnotationOnClassOrMethod(method, targetClass);
048                }
049
050                private boolean isMonitoredAnnotationOnClassOrMethod(Method method, Class targetClass) {
051                        return AnnotationUtils.findAnnotation(targetClass, Monitored.class) != null
052                                || AnnotationUtils.findAnnotation(AopUtils.getMostSpecificMethod(method, targetClass), Monitored.class) != null;
053                }
054
055                @Override
056                public boolean isRuntime() {
057                        return false;
058                }
059
060                @Override
061                public boolean matches(Method method, Class targetClass, Object[] args) {
062                        throw new UnsupportedOperationException("This is not a runtime method matcher");
063                }
064        }
065}