/* * Copyright 2014 NAVER Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.navercorp.pinpoint.plugin.spring.beans.interceptor; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig; import com.navercorp.pinpoint.bootstrap.util.PathMatcher; import com.navercorp.pinpoint.common.util.CollectionUtils; import com.navercorp.pinpoint.plugin.spring.beans.SpringBeansConfig; import com.navercorp.pinpoint.plugin.spring.beans.SpringBeansTarget; import com.navercorp.pinpoint.plugin.spring.beans.SpringBeansTargetScope; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; /** * @author Jongho Moon <jongho.moon@navercorp.com> * @author jaehong.kim */ public class TargetBeanFilter { private final List<SpringBeansTarget> targets; private static Cache cache = new Cache(); public static TargetBeanFilter of(ProfilerConfig profilerConfig) { SpringBeansConfig config = new SpringBeansConfig(profilerConfig); return new TargetBeanFilter(config.getTargets()); } public TargetBeanFilter(Collection<SpringBeansTarget> targets) { this.targets = new ArrayList<SpringBeansTarget>(targets); } public void clear() { cache.clear(); } public boolean isTarget(final SpringBeansTargetScope scope, final String beanName, final BeanDefinition beanDefinition) { if (scope == null || beanName == null || beanDefinition == null) { return false; } final String className = beanDefinition.getBeanClassName(); if (className == null) { return false; } if (cache.contains(className)) { return false; } for (SpringBeansTarget target : targets) { // check scope. if (target.getScope() != scope) { continue; } boolean condition = false; // check base packages. final List<String> basePackages = target.getBasePackages(); if (CollectionUtils.isNotEmpty(basePackages)) { if (!isBasePackage(target, className)) { continue; } condition = true; } // check bean name pattern. final List<PathMatcher> namePatterns = target.getNamePatterns(); if (CollectionUtils.isNotEmpty(namePatterns)) { if (!isBeanNameTarget(target, beanName)) { continue; } condition = true; } // check class name pattern. final List<PathMatcher> classPatterns = target.getClassPatterns(); if (CollectionUtils.isNotEmpty(classPatterns)) { if (!isClassNameTarget(target, className)) { continue; } condition = true; } // check class annotation. final List<String> annotations = target.getAnnotations(); if (CollectionUtils.isNotEmpty(annotations)) { if (!(beanDefinition instanceof AnnotatedBeanDefinition) || !isAnnotationTarget(target, (AnnotatedBeanDefinition) beanDefinition)) { continue; } condition = true; } if (condition) { // AND condition. return true; } } return false; } public boolean isTarget(final SpringBeansTargetScope scope, final String beanName, final Class<?> clazz) { if (scope == null || beanName == null || clazz == null) { return false; } final String className = clazz.getName(); if (className == null) { return false; } if (cache.contains(className)) { return false; } for (SpringBeansTarget target : targets) { // check scope. if (target.getScope() != scope) { continue; } boolean condition = false; // check base packages. final List<String> basePackages = target.getBasePackages(); if (CollectionUtils.isNotEmpty(basePackages)) { if (!isBasePackage(target, className)) { continue; } condition = true; } // check bean name pattern. final List<PathMatcher> namePatterns = target.getNamePatterns(); if (CollectionUtils.isNotEmpty(namePatterns)) { if (!isBeanNameTarget(target, beanName)) { continue; } condition = true; } // check class name pattern. final List<PathMatcher> classPatterns = target.getClassPatterns(); if (CollectionUtils.isNotEmpty(classPatterns)) { if (!isClassNameTarget(target, className)) { continue; } condition = true; } // check class annotation. final List<String> annotations = target.getAnnotations(); if (CollectionUtils.isNotEmpty(annotations)) { if (!isAnnotationTarget(target, clazz)) { continue; } condition = true; } if (condition) { // AND condition. return true; } } return false; } private boolean isBasePackage(final SpringBeansTarget target, final String className) { for (String basePackage : target.getBasePackages()) { if (className.startsWith(basePackage)) { return true; } } return false; } private boolean isBeanNameTarget(final SpringBeansTarget target, final String beanName) { for (PathMatcher pathMatcher : target.getNamePatterns()) { if (pathMatcher.isMatched(beanName)) { return true; } } return false; } private boolean isClassNameTarget(final SpringBeansTarget target, final String className) { for (PathMatcher pathMatcher : target.getClassPatterns()) { if (pathMatcher.isMatched(className)) { return true; } } return false; } private boolean isAnnotationTarget(final SpringBeansTarget target, final AnnotatedBeanDefinition annotatedBeanDefinition) { for (String annotationName : target.getAnnotations()) { if (annotatedBeanDefinition.getMetadata().hasAnnotation(annotationName)) { // annotation. return true; } if (annotatedBeanDefinition.getMetadata().hasMetaAnnotation(annotationName)) { // meta annotation. return true; } } return false; } private boolean isAnnotationTarget(final SpringBeansTarget target, final Class<?> clazz) { for (Annotation a : clazz.getAnnotations()) { if (target.getAnnotations().contains(a.annotationType().getName())) { return true; } } for (Annotation a : clazz.getAnnotations()) { for (Annotation ac : a.annotationType().getAnnotations()) { if (target.getAnnotations().contains(ac.annotationType().getName())) { return true; } } } return false; } public void addTransformed(final String className) { cache.put(className); } }