org.springframework.test.context.support.TestPropertySourceAttributes.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.test.context.support.TestPropertySourceAttributes.java

Source

/*
 * Copyright 2002-2017 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.context.support;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.style.ToStringCreator;
import org.springframework.lang.Nullable;
import org.springframework.test.context.TestPropertySource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ResourceUtils;

/**
 * {@code TestPropertySourceAttributes} encapsulates the attributes declared
 * via {@link TestPropertySource @TestPropertySource}.
 *
 * <p>In addition to encapsulating declared attributes,
 * {@code TestPropertySourceAttributes} also enforces configuration rules
 * and detects default properties files.
 *
 * @author Sam Brannen
 * @since 4.1
 * @see TestPropertySource
 * @see MergedTestPropertySources
 */
class TestPropertySourceAttributes {

    private static final Log logger = LogFactory.getLog(TestPropertySourceAttributes.class);

    private final Class<?> declaringClass;

    private final String[] locations;

    private final boolean inheritLocations;

    private final String[] properties;

    private final boolean inheritProperties;

    /**
     * Create a new {@code TestPropertySourceAttributes} instance for the
     * supplied {@link TestPropertySource @TestPropertySource} annotation and
     * the {@linkplain Class test class} that declared it, enforcing
     * configuration rules and detecting a default properties file if
     * necessary.
     * @param declaringClass the class that declared {@code @TestPropertySource}
     * @param testPropertySource the annotation from which to retrieve the attributes
     * @since 4.2
     */
    TestPropertySourceAttributes(Class<?> declaringClass, TestPropertySource testPropertySource) {
        this(declaringClass, testPropertySource.locations(), testPropertySource.inheritLocations(),
                testPropertySource.properties(), testPropertySource.inheritProperties());
    }

    private TestPropertySourceAttributes(Class<?> declaringClass, String[] locations, boolean inheritLocations,
            String[] properties, boolean inheritProperties) {

        Assert.notNull(declaringClass, "declaringClass must not be null");
        if (ObjectUtils.isEmpty(locations) && ObjectUtils.isEmpty(properties)) {
            locations = new String[] { detectDefaultPropertiesFile(declaringClass) };
        }
        this.declaringClass = declaringClass;
        this.locations = locations;
        this.inheritLocations = inheritLocations;
        this.properties = properties;
        this.inheritProperties = inheritProperties;
    }

    /**
     * Get the {@linkplain Class class} that declared {@code @TestPropertySource}.
     * @return the declaring class; never {@code null}
     */
    Class<?> getDeclaringClass() {
        return this.declaringClass;
    }

    /**
     * Get the resource locations that were declared via {@code @TestPropertySource}.
     * <p>Note: The returned value may represent a <em>detected default</em>
     * that does not match the original value declared via {@code @TestPropertySource}.
     * @return the resource locations; potentially <em>empty</em>
     * @see TestPropertySource#value
     * @see TestPropertySource#locations
     */
    String[] getLocations() {
        return this.locations;
    }

    /**
     * Get the {@code inheritLocations} flag that was declared via {@code @TestPropertySource}.
     * @return the {@code inheritLocations} flag
     * @see TestPropertySource#inheritLocations
     */
    boolean isInheritLocations() {
        return this.inheritLocations;
    }

    /**
     * Get the inlined properties that were declared via {@code @TestPropertySource}.
     * @return the inlined properties; potentially {@code null} or <em>empty</em>
     * @see TestPropertySource#properties
     */
    @Nullable
    String[] getProperties() {
        return this.properties;
    }

    /**
     * Get the {@code inheritProperties} flag that was declared via {@code @TestPropertySource}.
     * @return the {@code inheritProperties} flag
     * @see TestPropertySource#inheritProperties
     */
    boolean isInheritProperties() {
        return this.inheritProperties;
    }

    /**
     * Provide a String representation of the {@code @TestPropertySource}
     * attributes and declaring class.
     */
    @Override
    public String toString() {
        return new ToStringCreator(this)//
                .append("declaringClass", declaringClass.getName())//
                .append("locations", ObjectUtils.nullSafeToString(locations))//
                .append("inheritLocations", inheritLocations)//
                .append("properties", ObjectUtils.nullSafeToString(properties))//
                .append("inheritProperties", inheritProperties)//
                .toString();
    }

    /**
     * Detect a default properties file for the supplied class, as specified
     * in the class-level Javadoc for {@link TestPropertySource}.
     */
    private static String detectDefaultPropertiesFile(Class<?> testClass) {
        String resourcePath = ClassUtils.convertClassNameToResourcePath(testClass.getName()) + ".properties";
        String prefixedResourcePath = ResourceUtils.CLASSPATH_URL_PREFIX + resourcePath;
        ClassPathResource classPathResource = new ClassPathResource(resourcePath);

        if (classPathResource.exists()) {
            if (logger.isInfoEnabled()) {
                logger.info(String.format("Detected default properties file \"%s\" for test class [%s]",
                        prefixedResourcePath, testClass.getName()));
            }
            return prefixedResourcePath;
        } else {
            String msg = String.format(
                    "Could not detect default properties file for test [%s]: "
                            + "%s does not exist. Either declare the 'locations' or 'properties' attributes "
                            + "of @TestPropertySource or make the default properties file available.",
                    testClass.getName(), classPathResource);
            logger.error(msg);
            throw new IllegalStateException(msg);
        }
    }

}