ActivitySpec - Correcting logger messages
[sdc.git] / common / onap-common-configuration-management / onap-configuration-management-core / src / main / java / org / onap / config / impl / ConfigurationRepository.java
1 package org.onap.config.impl;
2
3 import org.apache.commons.configuration2.CombinedConfiguration;
4 import org.apache.commons.configuration2.CompositeConfiguration;
5 import org.apache.commons.configuration2.Configuration;
6 import org.apache.commons.configuration2.FileBasedConfiguration;
7 import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
8 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
9 import org.apache.commons.configuration2.ex.ConfigurationException;
10 import org.onap.config.ConfigurationUtils;
11 import org.onap.config.Constants;
12
13 import java.io.File;
14 import java.sql.Timestamp;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.HashSet;
20 import java.util.Iterator;
21 import java.util.LinkedHashMap;
22 import java.util.Map;
23 import java.util.Set;
24
25 /**
26  * The type Configuration repository.
27  */
28 public final class ConfigurationRepository {
29
30   /**
31    * The Repo.
32    */
33   static ConfigurationRepository repo;
34   private static Set<String> validCallers = Collections.unmodifiableSet(new HashSet<>(Arrays
35       .asList(ConfigurationChangeNotifier.NotificationData.class.getName(),
36           ConfigurationUtils.class.getName(), CliConfigurationImpl.class.getName(),
37           ConfigurationChangeNotifier.class.getName(), ConfigurationDataSource.class.getName(),
38           ConfigurationImpl.class.getName())));
39
40   static {
41     repo = new ConfigurationRepository();
42   }
43
44   private boolean dbAccessible = true;
45   private Set<String> tenants = new HashSet<>();
46   private Set<String> namespaces = new HashSet<>();
47   private LinkedHashMap<String, ConfigurationHolder> store =
48       new LinkedHashMap<String, ConfigurationHolder>(16, 0.75f, true) {
49         @Override
50         protected boolean removeEldestEntry(Map.Entry eldest) {
51           try {
52             return size() > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
53                 .getInt("config.size.max");
54           } catch (Exception exception) {
55             return false;
56           }
57         }
58       };
59
60   private ConfigurationRepository() {
61     if (repo != null) {
62       throw new RuntimeException("Illegal access to configuration.");
63     }
64     tenants.add(Constants.DEFAULT_TENANT);
65     namespaces.add(Constants.DEFAULT_NAMESPACE);
66   }
67
68   /**
69    * Lookup configuration repository.
70    *
71    * @return the configuration repository
72    */
73   public static ConfigurationRepository lookup() {
74     if (validCallers.contains(Thread.currentThread().getStackTrace()[2].getClassName())) {
75       return repo;
76     }
77     return null;
78   }
79
80   /**
81    * Gets tenants.
82    *
83    * @return the tenants
84    */
85   public Set<String> getTenants() {
86     return tenants;
87   }
88
89   /**
90    * Gets namespaces.
91    *
92    * @return the namespaces
93    */
94   public Set<String> getNamespaces() {
95     return namespaces;
96   }
97
98   private void populateTenantsNamespace(String key, boolean sourcedFromDb) {
99     String[] array = key.split(Constants.KEY_ELEMENTS_DELEMETER);
100     if (!array[1].equalsIgnoreCase(Constants.DB_NAMESPACE)) {
101       if (!sourcedFromDb) {
102         dbAccessible = false;
103       }
104       tenants.add(array[0]);
105       namespaces.add(array[1]);
106     }
107   }
108
109   /**
110    * Init tenants and namespaces.
111    */
112   public void initTenantsAndNamespaces() {
113     try {
114       Collection<String> collection = ConfigurationUtils.executeSelectSql(
115           getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
116               .getString("fetchnamescql"), new String[]{});
117       Iterator<String> iterator = collection.iterator();
118       while (iterator.hasNext()) {
119         populateTenantsNamespace(iterator.next(), true);
120       }
121     } catch (Exception exception) {
122       //Log this later
123     }
124   }
125
126   /**
127    * Is valid tenant boolean.
128    *
129    * @param tenant the tenant
130    * @return the boolean
131    */
132   public boolean isValidTenant(String tenant) {
133     return tenant == null ? false : tenants.contains(tenant.toUpperCase());
134   }
135
136   /**
137    * Is valid namespace boolean.
138    *
139    * @param namespace the namespace
140    * @return the boolean
141    */
142   public boolean isValidNamespace(String namespace) {
143     return namespace == null ? false : namespaces.contains(namespace.toUpperCase());
144   }
145
146   /**
147    * Gets configuration for.
148    *
149    * @param tenant    the tenant
150    * @param namespace the namespace
151    * @return the configuration for
152    * @throws Exception the exception
153    */
154   public Configuration getConfigurationFor(String tenant, String namespace) throws Exception {
155     ConfigurationHolder config;
156     String module = tenant + Constants.KEY_ELEMENTS_DELEMETER + namespace;
157     config = store.get(module);
158     if (config == null) {
159       config = new ConfigurationHolder(ConfigurationUtils
160           .getDbConfigurationBuilder(tenant + Constants.KEY_ELEMENTS_DELEMETER + namespace));
161       store.put(module, config);
162     }
163     return config.getConfiguration(tenant + Constants.KEY_ELEMENTS_DELEMETER + namespace);
164   }
165
166   /**
167    * Populate configurtaion.
168    *
169    * @param key     the key
170    * @param builder the builder
171    */
172   public void populateConfigurtaion(String key, Configuration builder) {
173     store.put(key, new ConfigurationHolder(builder));
174     populateTenantsNamespace(key, false);
175   }
176
177   /**
178    * Populate configurtaion.
179    *
180    * @param key     the key
181    * @param builder the builder
182    * @throws Exception the exception
183    */
184   public void populateConfigurtaion(String key, BasicConfigurationBuilder builder)
185       throws Exception {
186     store.put(key, new ConfigurationHolder(builder));
187   }
188
189   /**
190    * Populate override configurtaion.
191    *
192    * @param key  the key
193    * @param file the file
194    * @throws Exception the exception
195    */
196   public void populateOverrideConfigurtaion(String key, File file) throws Exception {
197     ConfigurationHolder holder = store.get(key);
198     if (holder == null) {
199       if (dbAccessible) {
200         holder = new ConfigurationHolder(ConfigurationUtils.getDbConfigurationBuilder(key));
201       } else {
202         holder = new ConfigurationHolder(new CombinedConfiguration());
203       }
204       store.put(key, holder);
205     }
206     holder.addOverrideConfiguration(file.getAbsolutePath(),
207         ConfigurationUtils.getConfigurationBuilder(file, true));
208     populateTenantsNamespace(key, true);
209   }
210
211   /**
212    * Refresh override configurtaion for.
213    *
214    * @param key   the key
215    * @param index the index
216    * @throws Exception the exception
217    */
218   public void refreshOverrideConfigurtaionFor(String key, int index) throws Exception {
219     ConfigurationHolder holder = store.get(key);
220     if (holder != null) {
221       holder.refreshOverrideConfiguration(index);
222     }
223   }
224
225   /**
226    * Remove override configurtaion.
227    *
228    * @param file the file
229    * @throws Exception the exception
230    */
231   public void removeOverrideConfigurtaion(File file) throws Exception {
232     Iterator<String> iterator = new ArrayList(store.keySet()).iterator();
233     while (iterator.hasNext()) {
234       ConfigurationHolder holder = store.get(iterator.next());
235       if (holder.containsOverrideConfiguration(file.getAbsolutePath())) {
236         holder.removeOverrideConfiguration(file.getAbsolutePath());
237       }
238     }
239
240   }
241
242   private class ConfigurationHolder {
243
244     /**
245      * The Builder.
246      */
247     BasicConfigurationBuilder<Configuration> builder;
248     /**
249      * The Last configuration build time.
250      */
251     Timestamp lastConfigurationBuildTime;
252     /**
253      * The Config.
254      */
255     Configuration config;
256     /**
257      * The Composite.
258      */
259     Configuration composite;
260     /**
261      * The Last config change timestamp.
262      */
263     Timestamp lastConfigChangeTimestamp;
264     private Map<String, FileBasedConfigurationBuilder<FileBasedConfiguration>>
265         overrideConfiguration = new LinkedHashMap<>();
266
267
268     /**
269      * Instantiates a new Configuration holder.
270      *
271      * @param builder the builder
272      */
273     public ConfigurationHolder(BasicConfigurationBuilder builder) {
274       this.builder = builder;
275     }
276
277     /**
278      * Instantiates a new Configuration holder.
279      *
280      * @param builder the builder
281      */
282     public ConfigurationHolder(Configuration builder) {
283       this.config = builder;
284     }
285
286     /**
287      * Refresh override configuration.
288      *
289      * @param index the index
290      */
291     public void refreshOverrideConfiguration(int index) {
292       int count = -1;
293       for (FileBasedConfigurationBuilder overrides : overrideConfiguration.values()) {
294         try {
295           if (++count == index) {
296             overrides.save();
297             overrides.resetResult();
298           }
299         } catch (ConfigurationException exception) {
300           //do nothing
301         }
302       }
303     }
304
305     /**
306      * Add override configuration.
307      *
308      * @param path    the path
309      * @param builder the builder
310      */
311     public void addOverrideConfiguration(String path,
312                                      BasicConfigurationBuilder<FileBasedConfiguration> builder) {
313       overrideConfiguration.put(path.toUpperCase(), (FileBasedConfigurationBuilder) builder);
314       getEffectiveConfiguration(config, overrideConfiguration.values());
315     }
316
317     /**
318      * Remove override configuration.
319      *
320      * @param path the path
321      */
322     public void removeOverrideConfiguration(String path) {
323       overrideConfiguration.remove(path.toUpperCase());
324       getEffectiveConfiguration(config, overrideConfiguration.values());
325     }
326
327     /**
328      * Contains override configuration boolean.
329      *
330      * @param path the path
331      * @return the boolean
332      */
333     public boolean containsOverrideConfiguration(String path) {
334       return overrideConfiguration.containsKey(path.toUpperCase());
335     }
336
337     /**
338      * Gets configuration.
339      *
340      * @param namespace the namespace
341      * @return the configuration
342      * @throws Exception the exception
343      */
344     public Configuration getConfiguration(String namespace) throws Exception {
345       if (config == null) {
346         config = builder.getConfiguration();
347         lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis());
348       } else if (lastConfigurationBuildTime != null
349           && System.currentTimeMillis() - lastConfigurationBuildTime.getTime()
350           > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
351                   .getInt("config.refresh.interval")) {
352         Timestamp temp = getLastUpdateTimestampFor(namespace);
353         if ((temp != null)
354             && (lastConfigChangeTimestamp == null
355             || temp.getTime() > lastConfigChangeTimestamp.getTime())) {
356           builder.resetResult();
357           config = builder.getConfiguration();
358           lastConfigChangeTimestamp = temp;
359           getEffectiveConfiguration(config, overrideConfiguration.values());
360         }
361         lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis());
362       }
363       if (composite == null && overrideConfiguration.size() != 0) {
364         composite = getEffectiveConfiguration(config, overrideConfiguration.values());
365       }
366       return overrideConfiguration.size() == 0 ? config : composite;
367     }
368
369     private Configuration getEffectiveConfiguration(Configuration configuration,
370                     Collection<FileBasedConfigurationBuilder<FileBasedConfiguration>> list) {
371       try {
372         CompositeConfiguration cc = new CompositeConfiguration();
373         for (FileBasedConfigurationBuilder<FileBasedConfiguration> b : list) {
374           cc.addConfiguration(b.getConfiguration());
375         }
376         cc.addConfiguration(configuration);
377         composite = cc;
378         return composite;
379       } catch (Exception exception) {
380         return null;
381       }
382     }
383
384     /**
385      * Gets last update timestamp for.
386      *
387      * @param namespace the namespace
388      * @return the last update timestamp for
389      */
390     public Timestamp getLastUpdateTimestampFor(String namespace) {
391       Timestamp timestamp = null;
392
393       try {
394         Collection<String> collection = ConfigurationUtils.executeSelectSql(
395             getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
396                 .getString("fetchlastchangecql"), new String[]{namespace});
397         if (!collection.isEmpty()) {
398           timestamp = new Timestamp(Long.valueOf(((ArrayList) collection).get(0).toString()));
399         }
400       } catch (Exception exception) {
401         //Log this later
402       }
403
404       return timestamp;
405     }
406
407
408   }
409
410   public boolean isDBAccessible(){
411     return dbAccessible;
412   }
413
414
415 }