5b950d1af62d4d90b3b74f11fc308bd510e5aee7
[sdc.git] / common / onap-common-configuration-management / onap-configuration-management-core / src / main / java / org / onap / config / impl / ConfigurationRepository.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package org.onap.config.impl;
18
19 import java.io.File;
20 import java.sql.Timestamp;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashSet;
25 import java.util.LinkedHashMap;
26 import java.util.Map;
27 import java.util.Set;
28 import org.apache.commons.configuration2.CombinedConfiguration;
29 import org.apache.commons.configuration2.CompositeConfiguration;
30 import org.apache.commons.configuration2.Configuration;
31 import org.apache.commons.configuration2.FileBasedConfiguration;
32 import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
33 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
34 import org.apache.commons.configuration2.ex.ConfigurationException;
35 import org.onap.config.ConfigurationUtils;
36 import org.onap.config.Constants;
37
38 public final class ConfigurationRepository {
39
40     private static final ConfigurationRepository repo = new ConfigurationRepository();
41
42     private final Set<String> tenants = Collections.synchronizedSet(new HashSet<>());
43
44     private final Set<String> namespaces = Collections.synchronizedSet(new HashSet<>());
45
46     private final Map<String, ConfigurationHolder> store = Collections.synchronizedMap(
47
48             new LinkedHashMap<String, ConfigurationHolder>(16, 0.75f, true) {
49
50                 @Override
51                 protected boolean removeEldestEntry(Map.Entry eldest) {
52                     try {
53                         return size() > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
54                                                 .getInt("config.size.max");
55                     } catch (Exception exception) {
56                         return false;
57                     }
58                 }
59             });
60
61
62     private ConfigurationRepository() {
63         tenants.add(Constants.DEFAULT_TENANT);
64         namespaces.add(Constants.DEFAULT_NAMESPACE);
65     }
66
67     public static ConfigurationRepository lookup() {
68         return repo;
69     }
70
71     public Set<String> getTenants() {
72         return tenants;
73     }
74
75     public Set<String> getNamespaces() {
76         return namespaces;
77     }
78
79
80     public boolean isValidTenant(String tenant) {
81         return tenant != null && tenants.contains(tenant.toUpperCase());
82     }
83
84     public boolean isValidNamespace(String namespace) {
85         return namespace != null && namespaces.contains(namespace.toUpperCase());
86     }
87
88     public Configuration getConfigurationFor(String tenant, String namespace) throws Exception {
89         String module = tenant + Constants.KEY_ELEMENTS_DELIMITER + namespace;
90         ConfigurationHolder config = store.get(module);
91         return config.getConfiguration(tenant + Constants.KEY_ELEMENTS_DELIMITER + namespace);
92     }
93
94     public void populateConfiguration(String key, Configuration builder) {
95         store.put(key, new ConfigurationHolder(builder));
96         populateTenantsNamespace(key);
97     }
98
99     private void populateTenantsNamespace(String key) {
100         String[] array = key.split(Constants.KEY_ELEMENTS_DELIMITER);
101         if (!array[1].equalsIgnoreCase(Constants.DB_NAMESPACE)) {
102             tenants.add(array[0]);
103             namespaces.add(array[1]);
104         }
105     }
106
107     public void populateOverrideConfiguration(String key, File file) {
108         ConfigurationHolder holder = store.get(key);
109         if (holder == null) {
110             holder = new ConfigurationHolder(new CombinedConfiguration());
111             store.put(key, holder);
112         }
113         holder.addOverrideConfiguration(file.getAbsolutePath(), ConfigurationUtils.getConfigurationBuilder(file, true));
114         populateTenantsNamespace(key);
115     }
116
117     public void refreshOverrideConfigurationFor(String key, int index) {
118         ConfigurationHolder holder = store.get(key);
119         if (holder != null) {
120             holder.refreshOverrideConfiguration(index);
121         }
122     }
123
124     public void removeOverrideConfiguration(File file) {
125         for (String s : (Iterable<String>) new ArrayList(store.keySet())) {
126             ConfigurationHolder holder = store.get(s);
127             if (holder.containsOverrideConfiguration(file.getAbsolutePath())) {
128                 holder.removeOverrideConfiguration(file.getAbsolutePath());
129             }
130         }
131     }
132
133     private class ConfigurationHolder {
134
135         private final Map<String, FileBasedConfigurationBuilder<FileBasedConfiguration>> overrideConfiguration =
136                 new LinkedHashMap<>();
137         BasicConfigurationBuilder<Configuration> builder;
138         Timestamp lastConfigurationBuildTime;
139         Configuration config;
140         Configuration composite;
141
142         public ConfigurationHolder(BasicConfigurationBuilder builder) {
143             this.builder = builder;
144         }
145
146         public ConfigurationHolder(Configuration builder) {
147             this.config = builder;
148         }
149
150         public void refreshOverrideConfiguration(int index) {
151             int count = -1;
152             for (FileBasedConfigurationBuilder overrides : overrideConfiguration.values()) {
153                 try {
154                     if (++count == index) {
155                         overrides.save();
156                         overrides.resetResult();
157                     }
158                 } catch (ConfigurationException exception) {
159                     //do nothing
160                 }
161             }
162         }
163
164         public void addOverrideConfiguration(String path, BasicConfigurationBuilder<FileBasedConfiguration> builder) {
165             overrideConfiguration.put(path.toUpperCase(), (FileBasedConfigurationBuilder) builder);
166             getEffectiveConfiguration(config, overrideConfiguration.values());
167         }
168
169         private Configuration getEffectiveConfiguration(Configuration configuration,
170                 Collection<FileBasedConfigurationBuilder<FileBasedConfiguration>> list) {
171             try {
172                 CompositeConfiguration cc = new CompositeConfiguration();
173                 for (FileBasedConfigurationBuilder<FileBasedConfiguration> b : list) {
174                     cc.addConfiguration(b.getConfiguration());
175                 }
176                 cc.addConfiguration(configuration);
177                 composite = cc;
178                 return composite;
179             } catch (Exception exception) {
180                 return null;
181             }
182         }
183
184         public void removeOverrideConfiguration(String path) {
185             overrideConfiguration.remove(path.toUpperCase());
186             getEffectiveConfiguration(config, overrideConfiguration.values());
187         }
188
189         public boolean containsOverrideConfiguration(String path) {
190             return overrideConfiguration.containsKey(path.toUpperCase());
191         }
192
193         public Configuration getConfiguration(String namespace) throws Exception {
194
195             if (config == null) {
196                 config = builder.getConfiguration();
197                 lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis());
198             } else if (lastConfigurationBuildTime != null
199                                && System.currentTimeMillis() - lastConfigurationBuildTime.getTime()
200                                           > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
201                                                     .getInt("config.refresh.interval")) {
202                 lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis());
203             }
204
205             if (composite == null && overrideConfiguration.size() != 0) {
206                 composite = getEffectiveConfiguration(config, overrideConfiguration.values());
207             }
208
209             return overrideConfiguration.size() == 0 ? config : composite;
210         }
211     }
212 }