2 * ================================================================================
3 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * ============LICENSE_END=========================================================
20 package org.onap.dcae.analytics.web.spring;
22 import java.util.Arrays;
23 import java.util.Collections;
25 import java.util.Optional;
27 import java.util.stream.Collectors;
29 import org.onap.dcae.analytics.model.AnalyticsProfile;
30 import org.onap.dcae.analytics.model.configbindingservice.ConfigBindingServiceConstants;
31 import org.onap.dcae.analytics.model.util.function.JsonStringToMapFunction;
32 import org.onap.dcae.analytics.model.util.supplier.ConfigBindingServiceJsonSupplier;
33 import org.onap.dcae.analytics.web.exception.AnalyticsValidationException;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36 import org.springframework.boot.SpringApplication;
37 import org.springframework.boot.env.EnvironmentPostProcessor;
38 import org.springframework.core.Ordered;
39 import org.springframework.core.env.ConfigurableEnvironment;
40 import org.springframework.core.env.MapPropertySource;
41 import org.springframework.core.env.MutablePropertySources;
42 import org.springframework.core.env.PropertySource;
43 import org.springframework.core.env.StandardEnvironment;
44 import org.springframework.util.ClassUtils;
45 import org.springframework.web.context.support.StandardServletEnvironment;
48 * A custom spring framework environment post processor which can fetch and populate spring context with
49 * Config Binding Service application properties.
51 * Activated only when config binding service profile is active.
53 * @author Rajiv Singla
55 public class ConfigBindingServiceEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
57 private static final Logger logger = LoggerFactory.getLogger(ConfigBindingServiceEnvironmentPostProcessor.class);
58 private static final String SERVLET_ENVIRONMENT_CLASS =
59 "org.springframework.web.context.support.StandardServletEnvironment";
61 private static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE;
64 public void postProcessEnvironment(final ConfigurableEnvironment environment, final SpringApplication application) {
66 final boolean isConfigServiceProfilePresent = Arrays.stream(environment.getActiveProfiles())
67 .anyMatch(p -> p.equalsIgnoreCase(AnalyticsProfile.CONFIG_BINDING_SERVICE_PROFILE_NAME));
69 if (!isConfigServiceProfilePresent) {
70 logger.info("Config Binding Service Profile is not active. " +
71 "Skipping Adding config binding service properties");
75 logger.info("Config Binding Service Profile is active. " +
76 "Application properties will be fetched from config binding service");
78 // Fetch config binding service json
79 final Optional<String> configServiceJsonOptional = new ConfigBindingServiceJsonSupplier().get();
81 if (!configServiceJsonOptional.isPresent()) {
82 final String errorMessage = "Unable to get fetch application configuration from config binding service";
83 throw new AnalyticsValidationException(errorMessage, new IllegalStateException(errorMessage));
86 final String configServicePropertiesKey = ConfigBindingServiceConstants.CONFIG_BINDING_SERVICE_PROPERTIES_KEY;
88 // convert fetch config binding service json string to Map of property key and values
89 final Map<String, Object> configPropertiesMap = configServiceJsonOptional
90 .map(new JsonStringToMapFunction(configServicePropertiesKey))
91 .orElse(Collections.emptyMap());
93 if (configPropertiesMap.isEmpty()) {
95 logger.warn("No properties found in config binding service");
99 // remove config service key prefix on spring reserved property key prefixes
100 final Set<String> springKeyPrefixes = ConfigBindingServiceConstants.SPRING_RESERVED_PROPERTIES_KEY_PREFIXES;
101 final Set<String> springKeys = springKeyPrefixes.stream()
102 .map(springKeyPrefix -> configServicePropertiesKey + "." + springKeyPrefix)
103 .collect(Collectors.toSet());
105 final Map<String, Object> filterKeyMap = configPropertiesMap.entrySet()
107 .collect(Collectors.toMap(
108 (Map.Entry<String, Object> e) ->
109 springKeys.stream().anyMatch(springKey -> e.getKey().startsWith(springKey)) ?
110 e.getKey().substring(configServicePropertiesKey.toCharArray().length + 1) :
115 filterKeyMap.forEach((key, value) ->
116 logger.info("Adding property from config service in spring context: {} -> {}", key, value));
118 addJsonPropertySource(environment, new MapPropertySource(configServicePropertiesKey, filterKeyMap));
124 public int getOrder() {
125 return DEFAULT_ORDER;
129 private void addJsonPropertySource(final ConfigurableEnvironment environment, final PropertySource<?> source) {
130 final MutablePropertySources sources = environment.getPropertySources();
131 final String name = findPropertySource(sources);
132 if (sources.contains(name)) {
133 sources.addBefore(name, source);
135 sources.addFirst(source);
139 private String findPropertySource(final MutablePropertySources sources) {
140 if (ClassUtils.isPresent(SERVLET_ENVIRONMENT_CLASS, null) &&
141 sources.contains(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME)) {
142 return StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME;
145 return StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME;