001/*
002 * Copyright 2012-2016 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.util.Properties;
021
022import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
023import org.springframework.boot.autoconfigure.condition.ConditionMessage;
024import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
025import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
026import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
027import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
028import org.springframework.boot.bind.RelaxedPropertyResolver;
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.PropertyResolver;
037import org.springframework.core.io.DefaultResourceLoader;
038import org.springframework.core.io.Resource;
039import org.springframework.core.io.ResourceLoader;
040import org.springframework.core.io.support.PropertiesLoaderUtils;
041import org.springframework.core.type.AnnotatedTypeMetadata;
042
043/**
044 * {@link EnableAutoConfiguration Auto-configuration} for various project information.
045 *
046 * @author Stephane Nicoll
047 * @since 1.4.0
048 */
049@Configuration
050@EnableConfigurationProperties(ProjectInfoProperties.class)
051public class ProjectInfoAutoConfiguration {
052
053        private final ProjectInfoProperties properties;
054
055        public ProjectInfoAutoConfiguration(ProjectInfoProperties properties) {
056                this.properties = properties;
057        }
058
059        @Conditional(GitResourceAvailableCondition.class)
060        @ConditionalOnMissingBean
061        @Bean
062        public GitProperties gitProperties() throws Exception {
063                return new GitProperties(loadFrom(this.properties.getGit().getLocation(), "git"));
064        }
065
066        @ConditionalOnResource(resources = "${spring.info.build.location:classpath:META-INF/build-info.properties}")
067        @ConditionalOnMissingBean
068        @Bean
069        public BuildProperties buildProperties() throws Exception {
070                return new BuildProperties(
071                                loadFrom(this.properties.getBuild().getLocation(), "build"));
072        }
073
074        protected Properties loadFrom(Resource location, String prefix) throws IOException {
075                String p = prefix.endsWith(".") ? prefix : prefix + ".";
076                Properties source = PropertiesLoaderUtils.loadProperties(location);
077                Properties target = new Properties();
078                for (String key : source.stringPropertyNames()) {
079                        if (key.startsWith(p)) {
080                                target.put(key.substring(p.length()), source.get(key));
081                        }
082                }
083                return target;
084        }
085
086        static class GitResourceAvailableCondition extends SpringBootCondition {
087
088                private final ResourceLoader defaultResourceLoader = new DefaultResourceLoader();
089
090                @Override
091                public ConditionOutcome getMatchOutcome(ConditionContext context,
092                                AnnotatedTypeMetadata metadata) {
093                        ResourceLoader loader = context.getResourceLoader();
094                        if (loader == null) {
095                                loader = this.defaultResourceLoader;
096                        }
097                        PropertyResolver propertyResolver = context.getEnvironment();
098                        RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
099                                        propertyResolver, "spring.info.git.");
100                        String location = resolver.getProperty("location");
101                        if (location == null) {
102                                resolver = new RelaxedPropertyResolver(propertyResolver, "spring.git.");
103                                location = resolver.getProperty("properties");
104                                if (location == null) {
105                                        location = "classpath:git.properties";
106                                }
107                        }
108                        ConditionMessage.Builder message = ConditionMessage
109                                        .forCondition("GitResource");
110                        if (loader.getResource(location).exists()) {
111                                return ConditionOutcome
112                                                .match(message.found("git info at").items(location));
113                        }
114                        return ConditionOutcome
115                                        .noMatch(message.didNotFind("git info at").items(location));
116                }
117
118        }
119
120}