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;
20 import java.sql.Timestamp;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.LinkedHashMap;
29 import org.apache.commons.configuration2.CombinedConfiguration;
30 import org.apache.commons.configuration2.CompositeConfiguration;
31 import org.apache.commons.configuration2.Configuration;
32 import org.apache.commons.configuration2.FileBasedConfiguration;
33 import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
34 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
35 import org.apache.commons.configuration2.ex.ConfigurationException;
36 import org.onap.config.ConfigurationUtils;
37 import org.onap.config.Constants;
39 public final class ConfigurationRepository {
41 private static final ConfigurationRepository repo;
43 private static final Set<String> validCallers = Collections.unmodifiableSet(new HashSet<>(
44 Arrays.asList(ConfigurationChangeNotifier.NotificationData.class.getName(),
45 ConfigurationUtils.class.getName(), CliConfigurationImpl.class.getName(),
46 ConfigurationChangeNotifier.class.getName(), ConfigurationImpl.class.getName())));
49 repo = new ConfigurationRepository();
52 private final Set<String> tenants = new HashSet<>();
53 private final Set<String> namespaces = new HashSet<>();
54 private final LinkedHashMap<String, ConfigurationHolder> store =
55 new LinkedHashMap<String, ConfigurationHolder>(16, 0.75f, true) {
57 protected boolean removeEldestEntry(Map.Entry eldest) {
59 return size() > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
60 .getInt("config.size.max");
61 } catch (Exception exception) {
67 private ConfigurationRepository() {
69 throw new RuntimeException("Illegal access to configuration.");
71 tenants.add(Constants.DEFAULT_TENANT);
72 namespaces.add(Constants.DEFAULT_NAMESPACE);
75 public static ConfigurationRepository lookup() {
76 if (validCallers.contains(Thread.currentThread().getStackTrace()[2].getClassName())) {
82 public Set<String> getTenants() {
86 public Set<String> getNamespaces() {
91 public boolean isValidTenant(String tenant) {
92 return tenant != null && tenants.contains(tenant.toUpperCase());
95 public boolean isValidNamespace(String namespace) {
96 return namespace != null && namespaces.contains(namespace.toUpperCase());
99 public Configuration getConfigurationFor(String tenant, String namespace) throws Exception {
100 ConfigurationHolder config;
101 String module = tenant + Constants.KEY_ELEMENTS_DELIMETER + namespace;
102 config = store.get(module);
103 if (config == null) {
104 config = new ConfigurationHolder(new BasicConfigurationBuilder<>(AgglomerateConfiguration.class));
105 store.put(module, config);
107 return config.getConfiguration(tenant + Constants.KEY_ELEMENTS_DELIMETER + namespace);
110 public void populateConfiguration(String key, Configuration builder) {
111 store.put(key, new ConfigurationHolder(builder));
112 populateTenantsNamespace(key, false);
115 private void populateTenantsNamespace(String key, boolean sourcedFromDb) {
116 String[] array = key.split(Constants.KEY_ELEMENTS_DELIMETER);
117 if (!array[1].equalsIgnoreCase(Constants.DB_NAMESPACE)) {
118 tenants.add(array[0]);
119 namespaces.add(array[1]);
123 public void populateOverrideConfiguration(String key, File file) {
124 ConfigurationHolder holder = store.get(key);
125 if (holder == null) {
126 holder = new ConfigurationHolder(new CombinedConfiguration());
127 store.put(key, holder);
129 holder.addOverrideConfiguration(file.getAbsolutePath(), ConfigurationUtils.getConfigurationBuilder(file, true));
130 populateTenantsNamespace(key, true);
133 public void refreshOverrideConfigurationFor(String key, int index) {
134 ConfigurationHolder holder = store.get(key);
135 if (holder != null) {
136 holder.refreshOverrideConfiguration(index);
140 public void removeOverrideConfiguration(File file) {
141 for (String s : (Iterable<String>) new ArrayList(store.keySet())) {
142 ConfigurationHolder holder = store.get(s);
143 if (holder.containsOverrideConfiguration(file.getAbsolutePath())) {
144 holder.removeOverrideConfiguration(file.getAbsolutePath());
149 private class ConfigurationHolder {
151 private final Map<String, FileBasedConfigurationBuilder<FileBasedConfiguration>> overrideConfiguration =
152 new LinkedHashMap<>();
153 BasicConfigurationBuilder<Configuration> builder;
154 Timestamp lastConfigurationBuildTime;
155 Configuration config;
156 Configuration composite;
158 public ConfigurationHolder(BasicConfigurationBuilder builder) {
159 this.builder = builder;
162 public ConfigurationHolder(Configuration builder) {
163 this.config = builder;
166 public void refreshOverrideConfiguration(int index) {
168 for (FileBasedConfigurationBuilder overrides : overrideConfiguration.values()) {
170 if (++count == index) {
172 overrides.resetResult();
174 } catch (ConfigurationException exception) {
180 public void addOverrideConfiguration(String path, BasicConfigurationBuilder<FileBasedConfiguration> builder) {
181 overrideConfiguration.put(path.toUpperCase(), (FileBasedConfigurationBuilder) builder);
182 getEffectiveConfiguration(config, overrideConfiguration.values());
185 private Configuration getEffectiveConfiguration(Configuration configuration,
186 Collection<FileBasedConfigurationBuilder<FileBasedConfiguration>> list) {
188 CompositeConfiguration cc = new CompositeConfiguration();
189 for (FileBasedConfigurationBuilder<FileBasedConfiguration> b : list) {
190 cc.addConfiguration(b.getConfiguration());
192 cc.addConfiguration(configuration);
195 } catch (Exception exception) {
200 public void removeOverrideConfiguration(String path) {
201 overrideConfiguration.remove(path.toUpperCase());
202 getEffectiveConfiguration(config, overrideConfiguration.values());
205 public boolean containsOverrideConfiguration(String path) {
206 return overrideConfiguration.containsKey(path.toUpperCase());
209 public Configuration getConfiguration(String namespace) throws Exception {
210 if (config == null) {
211 config = builder.getConfiguration();
212 lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis());
213 } else if (lastConfigurationBuildTime != null
214 && System.currentTimeMillis() - lastConfigurationBuildTime.getTime()
215 > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
216 .getInt("config.refresh.interval")) {
217 lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis());
219 if (composite == null && overrideConfiguration.size() != 0) {
220 composite = getEffectiveConfiguration(config, overrideConfiguration.values());
222 return overrideConfiguration.size() == 0 ? config : composite;