/***************************************************************************
* 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.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Scope;
import javax.inject.Singleton;
import org.apache.commons.lang.Validate;
/**
* Class for finding the scope of beans and factory methods.
*
* @author Christian Ihle
*/
public class AnnotationBasedScopeHandler {
private static final Class<Scope> SCOPE_ANNOTATION = Scope.class;
/**
* Checks if the bean has a singleton scope.
*
* <p>Rules:</p>
* <ul>
* <li>There can be at most 1 scope annotation.</li>
* <li>If no scope annotations are found, then <code>false</code> is returned.</li>
* <li>If the {@link Singleton} annotation is found, then <code>true</code> is returned.</li>
* <li>If any other scope annotation is found, then an exception is thrown.</li>
* </ul>
*
* @param beanClass The bean class to check the scope of.
* @return If the bean is a singleton.
*/
public boolean isSingleton(final Class<?> beanClass) {
return isSingletonInternal(beanClass);
}
/**
* Checks if the factory method has a singleton scope.
*
* <p>Rules:</p>
* <ul>
* <li>There can be at most 1 scope annotation.</li>
* <li>If no scope annotations are found, then <code>false</code> is returned.</li>
* <li>If the {@link Singleton} annotation is found, then <code>true</code> is returned.</li>
* <li>If any other scope annotation is found, then an exception is thrown.</li>
* </ul>
*
* @param factoryMethod The factory method to check the scope of.
* @return If the factory method creates a singleton.
*/
public boolean isSingleton(final Method factoryMethod) {
return isSingletonInternal(factoryMethod);
}
private boolean isSingletonInternal(final AnnotatedElement annotatedElement) {
Validate.notNull(annotatedElement, "Can't find scope of null");
final Annotation scope = getScope(annotatedElement);
if (scope instanceof Singleton) {
return true;
}
if (scope == null) {
return false;
}
throw new UnsupportedOperationException("Unknown scope on " + annotatedElement + " " + scope);
}
private Annotation getScope(final AnnotatedElement beanClass) {
final List<Annotation> matches = new ArrayList<Annotation>();
final Annotation[] annotations = beanClass.getAnnotations();
for (final Annotation annotation : annotations) {
if (annotation.annotationType().isAnnotationPresent(SCOPE_ANNOTATION)) {
matches.add(annotation);
}
}
if (matches.size() == 0) {
return null;
}
else if (matches.size() > 1) {
throw new UnsupportedOperationException(
"Wrong number of scope annotations found on " + beanClass + " " + matches);
}
return matches.get(0);
}
}