/*************************************************************************** * Copyright 2009-2012 by Christian Ihle * * kontakt@usikkert.net * * * * This file is part of KouInject. * * * * KouInject is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version. * * * * KouInject is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with KouInject. * * If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ package net.usikkert.kouinject; import java.lang.annotation.Annotation; import java.util.HashSet; import java.util.Set; import net.usikkert.kouinject.annotation.Component; import net.usikkert.kouinject.beandata.BeanKey; import net.usikkert.kouinject.profile.ProfileHandler; import org.apache.commons.lang.Validate; /** * Implementation of {@link BeanLocator} using the {@link Component} annotation to detect beans. * * @author Christian Ihle */ public class AnnotationBasedBeanLocator implements BeanLocator { private static final Class<Component> COMPONENT_ANNOTATION = Component.class; private final ClassLocator classLocator; private final String[] basePackages; private final AnnotationBasedQualifierHandler qualifierHandler; private final ProfileHandler profileHandler; /** * Constructs a new instance of this {@link BeanLocator} using a {@link ClassLocator} for * autodetecting the beans in the specified base packages. * * @param classLocator The instance of {@link ClassLocator} to use for finding the classes * that are bean candidates. * @param profileHandler The handler to use when deciding if a bean has an active profile. * @param basePackages A set of packages to start scanning for beans. All sub-packages will also be scanned. */ public AnnotationBasedBeanLocator(final ClassLocator classLocator, final ProfileHandler profileHandler, final String... basePackages) { Validate.notNull(classLocator, "Class locator can not be null"); Validate.notNull(profileHandler, "Profile handler can not be null"); Validate.notNull(basePackages, "Base packages can not be null"); this.basePackages = basePackages; this.classLocator = classLocator; this.profileHandler = profileHandler; this.qualifierHandler = new AnnotationBasedQualifierHandler(); } /** * {@inheritDoc} */ @Override public Set<BeanKey> findBeans() { final Set<Class<?>> allClasses = classLocator.findClasses(basePackages); final Set<BeanKey> detectedBeans = new HashSet<BeanKey>(); for (final Class<?> clazz : allClasses) { if (classIsBean(clazz) && profileHandler.beanIsActive(clazz)) { final String qualifier = getQualifier(clazz); final BeanKey bean = new BeanKey(clazz, qualifier); detectedBeans.add(bean); } } return detectedBeans; } private boolean classIsBean(final Class<?> clazz) { return classHasRegularComponent(clazz) || classHasCustomComponent(clazz); } private boolean classHasRegularComponent(final Class<?> clazz) { return clazz.isAnnotationPresent(COMPONENT_ANNOTATION); } private boolean classHasCustomComponent(final Class<?> clazz) { final Annotation[] annotations = clazz.getAnnotations(); for (final Annotation annotation : annotations) { final Class<? extends Annotation> annotationType = annotation.annotationType(); if (annotationType.isAnnotationPresent(COMPONENT_ANNOTATION)) { return true; } } return false; } private String getQualifier(final Class<?> clazz) { final Annotation[] annotations = clazz.getAnnotations(); return qualifierHandler.getQualifier(clazz, annotations); } }