2 * Copyright © 2016-2018 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onap.config.impl;
19 import static org.onap.config.Constants.LOAD_ORDER_KEY;
22 import java.net.MalformedURLException;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.HashMap;
28 import java.util.LinkedHashMap;
30 import org.apache.commons.configuration2.CombinedConfiguration;
31 import org.apache.commons.configuration2.Configuration;
32 import org.apache.commons.configuration2.ex.ConfigurationException;
33 import org.apache.commons.configuration2.tree.MergeCombiner;
34 import org.apache.commons.configuration2.tree.OverrideCombiner;
35 import org.apache.commons.configuration2.tree.UnionCombiner;
36 import org.onap.config.ConfigurationUtils;
37 import org.onap.config.type.ConfigurationMode;
39 public final class AggregateConfiguration {
41 private final Map<String, Configuration> rootConfig = Collections.synchronizedMap(new HashMap<>());
42 private final Map<String, Configuration> unionConfig = Collections.synchronizedMap(new HashMap<>());
43 private final Map<String, Configuration> mergeConfig = Collections.synchronizedMap(new HashMap<>());
44 private final Map<String, Configuration> overrideConfig = Collections.synchronizedMap(new LinkedHashMap<>());
46 public void addConfig(File file) throws ConfigurationException {
47 addConfig(fileToUrl(file), ConfigurationUtils.getMergeStrategy(file),
48 ConfigurationUtils.getConfigurationBuilder(file).getConfiguration());
51 public void addConfig(URL url) throws ConfigurationException {
52 addConfig(url, ConfigurationUtils.getMergeStrategy(url),
53 ConfigurationUtils.getConfigurationBuilder(url).getConfiguration());
56 private void addConfig(URL url, ConfigurationMode configMode, Configuration config) {
58 String normalizedUrl = normalize(url);
59 if (configMode != null) {
62 mergeConfig.put(normalizedUrl, config);
65 overrideConfig.put(normalizedUrl, config);
68 unionConfig.put(normalizedUrl, config);
73 rootConfig.put(normalizedUrl, config);
77 private String normalize(URL url) {
78 // what about Linux where paths are case sensitive?
79 return url.toString().toUpperCase();
82 private URL fileToUrl(File file) {
85 return file.getAbsoluteFile().toURI().toURL();
86 } catch (MalformedURLException e) {
87 throw new IllegalStateException("URL produced by JDK and is not expected to be malformed. File: "
88 + file.getAbsoluteFile());
92 public Configuration getFinalConfiguration() {
94 CombinedConfiguration ccRoot = new CombinedConfiguration(new MergeCombiner());
95 ArrayList<Configuration> tempList = new ArrayList<>(rootConfig.values());
96 tempList.sort(this::sortForMerge);
97 for (Configuration conf : tempList) {
98 ccRoot.addConfiguration(conf);
101 CombinedConfiguration ccMergeRoot = new CombinedConfiguration(new MergeCombiner());
102 ccMergeRoot.addConfiguration(ccRoot);
103 tempList = new ArrayList<>(mergeConfig.values());
104 tempList.sort(this::sortForMerge);
105 for (Configuration conf : tempList) {
106 ccMergeRoot.addConfiguration(conf);
109 CombinedConfiguration ccUnionRoot = new CombinedConfiguration(new UnionCombiner());
110 ccUnionRoot.addConfiguration(ccMergeRoot);
111 for (Configuration conf : unionConfig.values()) {
112 ccUnionRoot.addConfiguration(conf);
115 ArrayList<Configuration> tempOverrideConfigs = new ArrayList<>(overrideConfig.values());
116 Collections.reverse(tempOverrideConfigs);
117 tempOverrideConfigs.sort(this::sortForOverride);
118 CombinedConfiguration ccOverrideRoot = new CombinedConfiguration(new OverrideCombiner());
119 for (Configuration conf : tempOverrideConfigs) {
120 ccOverrideRoot.addConfiguration(conf);
123 ccOverrideRoot.addConfiguration(ccUnionRoot);
124 return ccOverrideRoot;
127 private int sortForOverride(Configuration conf1, Configuration conf2) {
128 return sort(conf1, conf2, (o1, o2) -> o2 - o1);
131 private int sortForMerge(Configuration conf1, Configuration conf2) {
132 return sort(conf1, conf2, (o1, o2) -> o1 - o2);
135 private int sort(Configuration conf1, Configuration conf2, Comparator<Integer> comparator) {
136 int order1 = readLoadOrder(conf1);
137 int order2 = readLoadOrder(conf2);
138 return comparator.compare(order1, order2);
141 private int readLoadOrder(Configuration conf) {
143 String order = conf.getString(LOAD_ORDER_KEY);
144 if (ConfigurationUtils.isBlank(order) || !order.trim().matches("\\d+")) {
148 return Integer.parseInt(order.trim());