/* * Copyright 2002-2008 the original author or authors. * * 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 org.springframework.test.annotation; import java.lang.reflect.Method; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** * General utility methods for working with <em>profile values</em>. * * @author Sam Brannen * @author Juergen Hoeller * @since 2.5 * @see ProfileValueSource * @see ProfileValueSourceConfiguration * @see IfProfileValue */ public abstract class ProfileValueUtils { private static final Log logger = LogFactory.getLog(ProfileValueUtils.class); /** * Retrieves the {@link ProfileValueSource} type for the specified * {@link Class test class} as configured via the * {@link ProfileValueSourceConfiguration @ProfileValueSourceConfiguration} * annotation and instantiates a new instance of that type. * <p> * If * {@link ProfileValueSourceConfiguration @ProfileValueSourceConfiguration} * is not present on the specified class or if a custom * {@link ProfileValueSource} is not declared, the default * {@link SystemProfileValueSource} will be returned instead. * * @param testClass The test class for which the ProfileValueSource should * be retrieved * @return the configured (or default) ProfileValueSource for the specified * class * @see SystemProfileValueSource */ @SuppressWarnings("unchecked") public static ProfileValueSource retrieveProfileValueSource(Class<?> testClass) { Assert.notNull(testClass, "testClass must not be null"); Class<ProfileValueSourceConfiguration> annotationType = ProfileValueSourceConfiguration.class; ProfileValueSourceConfiguration config = testClass.getAnnotation(annotationType); if (logger.isDebugEnabled()) { logger.debug("Retrieved @ProfileValueSourceConfiguration [" + config + "] for test class [" + testClass.getName() + "]"); } Class<? extends ProfileValueSource> profileValueSourceType; if (config != null) { profileValueSourceType = config.value(); } else { profileValueSourceType = (Class<? extends ProfileValueSource>) AnnotationUtils.getDefaultValue(annotationType); } if (logger.isDebugEnabled()) { logger.debug("Retrieved ProfileValueSource type [" + profileValueSourceType + "] for class [" + testClass.getName() + "]"); } ProfileValueSource profileValueSource; if (SystemProfileValueSource.class.equals(profileValueSourceType)) { profileValueSource = SystemProfileValueSource.getInstance(); } else { try { profileValueSource = profileValueSourceType.newInstance(); } catch (Exception e) { if (logger.isWarnEnabled()) { logger.warn("Could not instantiate a ProfileValueSource of type [" + profileValueSourceType + "] for class [" + testClass.getName() + "]: using default.", e); } profileValueSource = SystemProfileValueSource.getInstance(); } } return profileValueSource; } /** * Determine if the supplied <code>testClass</code> is <em>enabled</em> * in the current environment, as specified by the * {@link IfProfileValue @IfProfileValue} annotation at the class level. * <p> * Defaults to <code>true</code> if no * {@link IfProfileValue @IfProfileValue} annotation is declared. * * @param testClass the test class * @return <code>true</code> if the test is <em>enabled</em> in the * current environment */ public static boolean isTestEnabledInThisEnvironment(Class<?> testClass) { IfProfileValue ifProfileValue = testClass.getAnnotation(IfProfileValue.class); if (ifProfileValue == null) { return true; } ProfileValueSource profileValueSource = retrieveProfileValueSource(testClass); return isTestEnabledInThisEnvironment(profileValueSource, ifProfileValue); } /** * Determine if the supplied <code>testMethod</code> is <em>enabled</em> * in the current environment, as specified by the * {@link IfProfileValue @IfProfileValue} annotation, which may be declared * on the test method itself or at the class level. * <p> * Defaults to <code>true</code> if no * {@link IfProfileValue @IfProfileValue} annotation is declared. * * @param testMethod the test method * @param testClass the test class * @return <code>true</code> if the test is <em>enabled</em> in the * current environment */ public static boolean isTestEnabledInThisEnvironment(Method testMethod, Class<?> testClass) { IfProfileValue ifProfileValue = testMethod.getAnnotation(IfProfileValue.class); if (ifProfileValue == null) { ifProfileValue = testClass.getAnnotation(IfProfileValue.class); if (ifProfileValue == null) { return true; } } ProfileValueSource profileValueSource = retrieveProfileValueSource(testClass); return isTestEnabledInThisEnvironment(profileValueSource, ifProfileValue); } /** * Determine if the supplied <code>testMethod</code> is <em>enabled</em> * in the current environment, as specified by the * {@link IfProfileValue @IfProfileValue} annotation, which may be declared * on the test method itself or at the class level. * <p> * Defaults to <code>true</code> if no * {@link IfProfileValue @IfProfileValue} annotation is declared. * * @param profileValueSource the ProfileValueSource to use to determine if * the test is enabled * @param testMethod the test method * @param testClass the test class * @return <code>true</code> if the test is <em>enabled</em> in the * current environment */ public static boolean isTestEnabledInThisEnvironment(ProfileValueSource profileValueSource, Method testMethod, Class<?> testClass) { IfProfileValue ifProfileValue = testMethod.getAnnotation(IfProfileValue.class); if (ifProfileValue == null) { ifProfileValue = testClass.getAnnotation(IfProfileValue.class); if (ifProfileValue == null) { return true; } } return isTestEnabledInThisEnvironment(profileValueSource, ifProfileValue); } /** * Determine if the <code>value</code> (or one of the <code>values</code>) * in the supplied {@link IfProfileValue @IfProfileValue} annotation is * <em>enabled</em> in the current environment. * * @param profileValueSource the ProfileValueSource to use to determine if * the test is enabled * @param ifProfileValue the annotation to introspect * @return <code>true</code> if the test is <em>enabled</em> in the * current environment */ private static boolean isTestEnabledInThisEnvironment(ProfileValueSource profileValueSource, IfProfileValue ifProfileValue) { String environmentValue = profileValueSource.get(ifProfileValue.name()); String[] annotatedValues = ifProfileValue.values(); if (StringUtils.hasLength(ifProfileValue.value())) { if (annotatedValues.length > 0) { throw new IllegalArgumentException("Setting both the 'value' and 'values' attributes " + "of @IfProfileValue is not allowed: choose one or the other."); } annotatedValues = new String[] { ifProfileValue.value() }; } for (String value : annotatedValues) { if (ObjectUtils.nullSafeEquals(value, environmentValue)) { return true; } } return false; } }