org.springframework.boot.env.PropertySourcesLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.boot.env.PropertySourcesLoader.java

Source

/*
 * Copyright 2012-2015 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.boot.env;

import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

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

import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * Utility that can be used to {@link MutablePropertySources} using
 * {@link PropertySourceLoader}s.
 *
 * @author Phillip Webb
 */
public class PropertySourcesLoader {

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

    private final MutablePropertySources propertySources;

    private final List<PropertySourceLoader> loaders;

    /**
     * Create a new {@link PropertySourceLoader} instance backed by a new
     * {@link MutablePropertySources}.
     */
    public PropertySourcesLoader() {
        this(new MutablePropertySources());
    }

    /**
     * Create a new {@link PropertySourceLoader} instance backed by the specified
     * {@link MutablePropertySources}.
     * @param propertySources the destination property sources
     */
    public PropertySourcesLoader(MutablePropertySources propertySources) {
        Assert.notNull(propertySources, "PropertySources must not be null");
        this.propertySources = propertySources;
        this.loaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());
    }

    /**
     * Load the specified resource (if possible) and add it as the first source.
     * @param resource the source resource (may be {@code null}).
     * @return the loaded property source or {@code null}
     * @throws IOException if the source cannot be loaded
     */
    public PropertySource<?> load(Resource resource) throws IOException {
        return load(resource, null);
    }

    /**
     * Load the profile-specific properties from the specified resource (if any) and add
     * it as the first source.
     * @param resource the source resource (may be {@code null}).
     * @param profile a specific profile to load or {@code null} to load the default.
     * @return the loaded property source or {@code null}
     * @throws IOException if the source cannot be loaded
     */
    public PropertySource<?> load(Resource resource, String profile) throws IOException {
        return load(resource, resource.getDescription(), profile);
    }

    /**
     * Load the profile-specific properties from the specified resource (if any), give the
     * name provided and add it as the first source.
     * @param resource the source resource (may be {@code null}).
     * @param name the root property name (may be {@code null}).
     * @param profile a specific profile to load or {@code null} to load the default.
     * @return the loaded property source or {@code null}
     * @throws IOException if the source cannot be loaded
     */
    public PropertySource<?> load(Resource resource, String name, String profile) throws IOException {
        return load(resource, null, name, profile);
    }

    /**
     * Load the profile-specific properties from the specified resource (if any), give the
     * name provided and add it to a group of property sources identified by the group
     * name. Property sources are added to the end of a group, but new groups are added as
     * the first in the chain being assembled. This means the normal sequence of calls is
     * to first create the group for the default (null) profile, and then add specific
     * groups afterwards (with the highest priority last). Property resolution from the
     * resulting sources will consider all keys for a given group first and then move to
     * the next group.
     * @param resource the source resource (may be {@code null}).
     * @param group an identifier for the group that this source belongs to
     * @param name the root property name (may be {@code null}).
     * @param profile a specific profile to load or {@code null} to load the default.
     * @return the loaded property source or {@code null}
     * @throws IOException if the source cannot be loaded
     */
    public PropertySource<?> load(Resource resource, String group, String name, String profile) throws IOException {
        if (isFile(resource)) {
            String sourceName = generatePropertySourceName(name, profile);
            for (PropertySourceLoader loader : this.loaders) {
                if (canLoadFileExtension(loader, resource)) {
                    PropertySource<?> specific = loader.load(sourceName, resource, profile);
                    addPropertySource(group, specific, profile);
                    return specific;
                }
            }
        }
        return null;
    }

    private boolean isFile(Resource resource) {
        return resource != null && resource.exists()
                && StringUtils.hasText(StringUtils.getFilenameExtension(resource.getFilename()));
    }

    private String generatePropertySourceName(String name, String profile) {
        return (profile == null ? name : name + "#" + profile);
    }

    private boolean canLoadFileExtension(PropertySourceLoader loader, Resource resource) {
        String filename = resource.getFilename().toLowerCase();
        for (String extension : loader.getFileExtensions()) {
            if (filename.endsWith("." + extension.toLowerCase())) {
                return true;
            }
        }
        return false;
    }

    private void addPropertySource(String basename, PropertySource<?> source, String profile) {

        if (source == null) {
            return;
        }

        if (basename == null) {
            this.propertySources.addLast(source);
            return;
        }

        EnumerableCompositePropertySource group = getGeneric(basename);
        group.add(source);
        logger.trace("Adding PropertySource: " + source + " in group: " + basename);
        if (this.propertySources.contains(group.getName())) {
            this.propertySources.replace(group.getName(), group);
        } else {
            this.propertySources.addFirst(group);
        }

    }

    private EnumerableCompositePropertySource getGeneric(String name) {
        PropertySource<?> source = this.propertySources.get(name);
        if (source instanceof EnumerableCompositePropertySource) {
            return (EnumerableCompositePropertySource) source;
        }
        EnumerableCompositePropertySource composite = new EnumerableCompositePropertySource(name);
        return composite;
    }

    /**
     * Return the {@link MutablePropertySources} being loaded.
     * @return the property sources
     */
    public MutablePropertySources getPropertySources() {
        return this.propertySources;
    }

    /**
     * Returns all file extensions that could be loaded.
     * @return the file extensions
     */
    public Set<String> getAllFileExtensions() {
        Set<String> fileExtensions = new LinkedHashSet<String>();
        for (PropertySourceLoader loader : this.loaders) {
            fileExtensions.addAll(Arrays.asList(loader.getFileExtensions()));
        }
        return fileExtensions;
    }

}