001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.autoconfigure.info;
018
019import java.io.IOException;
020import java.nio.charset.Charset;
021import java.util.Properties;
022
023import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
024import org.springframework.boot.autoconfigure.condition.ConditionMessage;
025import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
026import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
027import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
028import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
029import org.springframework.boot.context.properties.EnableConfigurationProperties;
030import org.springframework.boot.info.BuildProperties;
031import org.springframework.boot.info.GitProperties;
032import org.springframework.context.annotation.Bean;
033import org.springframework.context.annotation.ConditionContext;
034import org.springframework.context.annotation.Conditional;
035import org.springframework.context.annotation.Configuration;
036import org.springframework.core.env.Environment;
037import org.springframework.core.io.DefaultResourceLoader;
038import org.springframework.core.io.Resource;
039import org.springframework.core.io.ResourceLoader;
040import org.springframework.core.io.support.EncodedResource;
041import org.springframework.core.io.support.PropertiesLoaderUtils;
042import org.springframework.core.type.AnnotatedTypeMetadata;
043
044/**
045 * {@link EnableAutoConfiguration Auto-configuration} for various project information.
046 *
047 * @author Stephane Nicoll
048 * @author Madhura Bhave
049 * @since 1.4.0
050 */
051@Configuration
052@EnableConfigurationProperties(ProjectInfoProperties.class)
053public class ProjectInfoAutoConfiguration {
054
055        private final ProjectInfoProperties properties;
056
057        public ProjectInfoAutoConfiguration(ProjectInfoProperties properties) {
058                this.properties = properties;
059        }
060
061        @Conditional(GitResourceAvailableCondition.class)
062        @ConditionalOnMissingBean
063        @Bean
064        public GitProperties gitProperties() throws Exception {
065                return new GitProperties(loadFrom(this.properties.getGit().getLocation(), "git",
066                                this.properties.getGit().getEncoding()));
067        }
068
069        @ConditionalOnResource(resources = "${spring.info.build.location:classpath:META-INF/build-info.properties}")
070        @ConditionalOnMissingBean
071        @Bean
072        public BuildProperties buildProperties() throws Exception {
073                return new BuildProperties(loadFrom(this.properties.getBuild().getLocation(),
074                                "build", this.properties.getBuild().getEncoding()));
075        }
076
077        protected Properties loadFrom(Resource location, String prefix, Charset encoding)
078                        throws IOException {
079                prefix = prefix.endsWith(".") ? prefix : prefix + ".";
080                Properties source = loadSource(location, encoding);
081                Properties target = new Properties();
082                for (String key : source.stringPropertyNames()) {
083                        if (key.startsWith(prefix)) {
084                                target.put(key.substring(prefix.length()), source.get(key));
085                        }
086                }
087                return target;
088        }
089
090        private Properties loadSource(Resource location, Charset encoding)
091                        throws IOException {
092                if (encoding != null) {
093                        return PropertiesLoaderUtils
094                                        .loadProperties(new EncodedResource(location, encoding));
095                }
096                return PropertiesLoaderUtils.loadProperties(location);
097        }
098
099        static class GitResourceAvailableCondition extends SpringBootCondition {
100
101                private final ResourceLoader defaultResourceLoader = new DefaultResourceLoader();
102
103                @Override
104                public ConditionOutcome getMatchOutcome(ConditionContext context,
105                                AnnotatedTypeMetadata metadata) {
106                        ResourceLoader loader = context.getResourceLoader();
107                        loader = (loader != null) ? loader : this.defaultResourceLoader;
108                        Environment environment = context.getEnvironment();
109                        String location = environment.getProperty("spring.info.git.location");
110                        if (location == null) {
111                                location = "classpath:git.properties";
112                        }
113                        ConditionMessage.Builder message = ConditionMessage
114                                        .forCondition("GitResource");
115                        if (loader.getResource(location).exists()) {
116                                return ConditionOutcome
117                                                .match(message.found("git info at").items(location));
118                        }
119                        return ConditionOutcome
120                                        .noMatch(message.didNotFind("git info at").items(location));
121                }
122
123        }
124
125}