001/*
002 * Copyright 2012-2017 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.env;
018
019import java.util.Map;
020
021import org.springframework.boot.SpringApplication;
022import org.springframework.boot.origin.Origin;
023import org.springframework.boot.origin.OriginLookup;
024import org.springframework.boot.origin.SystemEnvironmentOrigin;
025import org.springframework.core.Ordered;
026import org.springframework.core.env.ConfigurableEnvironment;
027import org.springframework.core.env.PropertySource;
028import org.springframework.core.env.StandardEnvironment;
029import org.springframework.core.env.SystemEnvironmentPropertySource;
030
031/**
032 * An {@link EnvironmentPostProcessor} that replaces the systemEnvironment
033 * {@link SystemEnvironmentPropertySource} with an
034 * {@link OriginAwareSystemEnvironmentPropertySource} that can track the
035 * {@link SystemEnvironmentOrigin} for every system environment property.
036 *
037 * @author Madhura Bhave
038 * @since 2.0.0
039 */
040public class SystemEnvironmentPropertySourceEnvironmentPostProcessor
041                implements EnvironmentPostProcessor, Ordered {
042
043        /**
044         * The default order for the processor.
045         */
046        public static final int DEFAULT_ORDER = SpringApplicationJsonEnvironmentPostProcessor.DEFAULT_ORDER
047                        - 1;
048
049        private int order = DEFAULT_ORDER;
050
051        @Override
052        public void postProcessEnvironment(ConfigurableEnvironment environment,
053                        SpringApplication application) {
054                String sourceName = StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME;
055                PropertySource<?> propertySource = environment.getPropertySources()
056                                .get(sourceName);
057                if (propertySource != null) {
058                        replacePropertySource(environment, sourceName, propertySource);
059                }
060        }
061
062        @SuppressWarnings("unchecked")
063        private void replacePropertySource(ConfigurableEnvironment environment,
064                        String sourceName, PropertySource<?> propertySource) {
065                Map<String, Object> originalSource = (Map<String, Object>) propertySource
066                                .getSource();
067                SystemEnvironmentPropertySource source = new OriginAwareSystemEnvironmentPropertySource(
068                                sourceName, originalSource);
069                environment.getPropertySources().replace(sourceName, source);
070        }
071
072        @Override
073        public int getOrder() {
074                return this.order;
075        }
076
077        public void setOrder(int order) {
078                this.order = order;
079        }
080
081        /**
082         * {@link SystemEnvironmentPropertySource} that also tracks {@link Origin}.
083         */
084        protected static class OriginAwareSystemEnvironmentPropertySource
085                        extends SystemEnvironmentPropertySource implements OriginLookup<String> {
086
087                OriginAwareSystemEnvironmentPropertySource(String name,
088                                Map<String, Object> source) {
089                        super(name, source);
090                }
091
092                @Override
093                public Origin getOrigin(String key) {
094                        String property = resolvePropertyName(key);
095                        if (super.containsProperty(property)) {
096                                return new SystemEnvironmentOrigin(property);
097                        }
098                        return null;
099                }
100
101        }
102
103}