com.netflix.spinnaker.kork.archaius.ArchaiusConfiguration.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.spinnaker.kork.archaius.ArchaiusConfiguration.java

Source

/*
 * Copyright 2015 Netflix, Inc.
 *
 * 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 com.netflix.spinnaker.kork.archaius;

import com.netflix.config.AbstractPollingScheduler;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicConfiguration;
import com.netflix.config.FixedDelayPollingScheduler;
import org.apache.commons.configuration.CompositeConfiguration;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePropertySource;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Configuration
public class ArchaiusConfiguration {

    /**
     * This is a BeanPostProcessor to ensure early initialization only.
     */
    static class ArchaiusInitializingBeanPostProcessor implements BeanPostProcessor, Ordered {
        private final ConfigurableApplicationContext applicationContext;
        private final AbstractPollingScheduler pollingScheduler;
        private final SpringEnvironmentPolledConfigurationSource polledConfigurationSource;
        private final List<ClasspathPropertySource> propertyBindings;
        private final DynamicConfiguration configurationInstance;

        public ArchaiusInitializingBeanPostProcessor(ConfigurableApplicationContext applicationContext,
                AbstractPollingScheduler pollingScheduler,
                SpringEnvironmentPolledConfigurationSource polledConfigurationSource,
                List<ClasspathPropertySource> propertyBindings) {
            this.applicationContext = Objects.requireNonNull(applicationContext, "applicationContext");
            this.pollingScheduler = Objects.requireNonNull(pollingScheduler, "pollingScheduler");
            this.polledConfigurationSource = Objects.requireNonNull(polledConfigurationSource,
                    "polledConfigurationSource");
            this.propertyBindings = propertyBindings != null ? propertyBindings : Collections.emptyList();
            initPropertyBindings();

            configurationInstance = new DynamicConfiguration(polledConfigurationSource, pollingScheduler);
            if (!ConfigurationManager.isConfigurationInstalled()) {
                ConfigurationManager.install(new CompositeConfiguration());
            }
            CompositeConfiguration config = (CompositeConfiguration) ConfigurationManager.getConfigInstance();
            config.addConfiguration(configurationInstance);

            applicationContext.getBeanFactory().registerSingleton("environmentBackedConfig",
                    ConfigurationManager.getConfigInstance());
            applicationContext.getBeanFactory().registerAlias("environmentBackedConfig", "abstractConfiguration");
        }

        @PreDestroy
        public void shutdown() {
            pollingScheduler.stop();
            ((CompositeConfiguration) ConfigurationManager.getConfigInstance())
                    .removeConfiguration(configurationInstance);
        }

        private void initPropertyBindings() {
            MutablePropertySources sources = applicationContext.getEnvironment().getPropertySources();
            Set<String> activeProfiles = new HashSet<>(
                    Arrays.asList(applicationContext.getEnvironment().getActiveProfiles()));
            for (ClasspathPropertySource binding : propertyBindings) {
                for (String profile : activeProfiles) {
                    if (binding.supportsProfile(profile)) {
                        res(binding.getBaseName(), profile).ifPresent(sources::addLast);
                    }
                }
                res(binding.getBaseName(), null).ifPresent(sources::addLast);
            }
        }

        private Optional<ResourcePropertySource> res(String base, String profile) {
            String name = base;
            String res = "/" + base;
            if (profile != null && !profile.isEmpty()) {
                name += ": " + profile;
                res += "-" + profile;
            }
            res += ".properties";
            Resource r = applicationContext.getResource(res);
            if (r.exists()) {
                try {
                    return Optional.of(new ResourcePropertySource(name, r));
                } catch (IOException ioe) {
                    throw new RuntimeException("Error loading property source [" + name + "]: " + res, ioe);
                }
            }
            return Optional.empty();
        }

        @Override
        public int getOrder() {
            return Ordered.HIGHEST_PRECEDENCE + 10;
        }

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }

    @Bean
    static AbstractPollingScheduler pollingScheduler(ConfigurableApplicationContext applicationContext) {
        int initialDelayMillis = applicationContext.getEnvironment()
                .getProperty(FixedDelayPollingScheduler.INITIAL_DELAY_PROPERTY, Integer.class, 0);
        int delayMillis = applicationContext.getEnvironment().getProperty(FixedDelayPollingScheduler.DELAY_PROPERTY,
                Integer.class, (int) TimeUnit.SECONDS.toMillis(15));
        return new FixedDelayPollingScheduler(initialDelayMillis, delayMillis, false);
    }

    @Bean
    static SpringEnvironmentPolledConfigurationSource polledConfigurationSource(
            ConfigurableApplicationContext applicationContext) {
        return new SpringEnvironmentPolledConfigurationSource(applicationContext.getEnvironment());
    }

    @Bean
    static ArchaiusInitializingBeanPostProcessor archaiusInitializingBeanPostProcessor(
            ConfigurableApplicationContext applicationContext,
            Optional<List<ClasspathPropertySource>> propertyBindings, AbstractPollingScheduler pollingScheduler,
            SpringEnvironmentPolledConfigurationSource polledConfigurationSource) {
        return new ArchaiusInitializingBeanPostProcessor(applicationContext, pollingScheduler,
                polledConfigurationSource, propertyBindings.orElse(Collections.emptyList()));
    }

}