[SDC-29] Amdocs OnBoard 1707 initial commit.
[sdc.git] / common / openecomp-common-configuration-management / openecomp-configuration-management-core / src / main / java / org / openecomp / config / impl / ConfigurationRepository.java
1 package org.openecomp.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.openecomp.config.ConfigurationUtils;
11 import org.openecomp.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         protected boolean removeEldestEntry(Map.Entry eldest) {
50           try {
51             return size() > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
52                 .getInt("config.size.max");
53           } catch (Exception exception) {
54             return false;
55           }
56         }
57       };
58
59   private ConfigurationRepository() {
60     if (repo != null) {
61       throw new RuntimeException("Illegal access to configuration.");
62     }
63     tenants.add(Constants.DEFAULT_TENANT);
64     namespaces.add(Constants.DEFAULT_NAMESPACE);
65   }
66
67   /**
68    * Lookup configuration repository.
69    *
70    * @return the configuration repository
71    */
72   public static ConfigurationRepository lookup() {
73     if (validCallers.contains(Thread.currentThread().getStackTrace()[2].getClassName())) {
74       return repo;
75     }
76     return null;
77   }
78
79   /**
80    * Gets tenants.
81    *
82    * @return the tenants
83    */
84   public Set<String> getTenants() {
85     return tenants;
86   }
87
88   /**
89    * Gets namespaces.
90    *
91    * @return the namespaces
92    */
93   public Set<String> getNamespaces() {
94     return namespaces;
95   }
96
97   private void populateTenantsNamespace(String key, boolean sourcedFromDb) {
98     String[] array = key.split(Constants.KEY_ELEMENTS_DELEMETER);
99     if (!array[1].toUpperCase().equals(Constants.DB_NAMESPACE)) {
100       if (!sourcedFromDb) {
101         dbAccessible = false;
102       }
103       tenants.add(array[0]);
104       namespaces.add(array[1]);
105     }
106   }
107
108   /**
109    * Init tenants and namespaces.
110    */
111   public void initTenantsAndNamespaces() {
112     try {
113       Collection<String> collection = ConfigurationUtils.executeSelectSql(
114           getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
115               .getString("fetchnamescql"), new String[]{});
116       Iterator<String> iterator = collection.iterator();
117       while (iterator.hasNext()) {
118         populateTenantsNamespace(iterator.next(), true);
119       }
120     } catch (Exception exception) {
121       //exception.printStackTrace();
122     }
123   }
124
125   /**
126    * Is valid tenant boolean.
127    *
128    * @param tenant the tenant
129    * @return the boolean
130    */
131   public boolean isValidTenant(String tenant) {
132     return tenant == null ? false : tenants.contains(tenant.toUpperCase());
133   }
134
135   /**
136    * Is valid namespace boolean.
137    *
138    * @param namespace the namespace
139    * @return the boolean
140    */
141   public boolean isValidNamespace(String namespace) {
142     return namespace == null ? false : namespaces.contains(namespace.toUpperCase());
143   }
144
145   /**
146    * Gets configuration for.
147    *
148    * @param tenant    the tenant
149    * @param namespace the namespace
150    * @return the configuration for
151    * @throws Exception the exception
152    */
153   public Configuration getConfigurationFor(String tenant, String namespace) throws Exception {
154     ConfigurationHolder config = null;
155     String module = tenant + Constants.KEY_ELEMENTS_DELEMETER + namespace;
156     config = store.get(module);
157     if (config == null) {
158       config = new ConfigurationHolder(ConfigurationUtils
159           .getDbConfigurationBuilder(tenant + Constants.KEY_ELEMENTS_DELEMETER + namespace));
160       store.put(module, config);
161     }
162     return config.getConfiguration(tenant + Constants.KEY_ELEMENTS_DELEMETER + namespace);
163   }
164
165   /**
166    * Populate configurtaion.
167    *
168    * @param key     the key
169    * @param builder the builder
170    */
171   public void populateConfigurtaion(String key, Configuration builder) {
172     store.put(key, new ConfigurationHolder(builder));
173     populateTenantsNamespace(key, false);
174   }
175
176   /**
177    * Populate configurtaion.
178    *
179    * @param key     the key
180    * @param builder the builder
181    * @throws Exception the exception
182    */
183   public void populateConfigurtaion(String key, BasicConfigurationBuilder builder)
184       throws Exception {
185     store.put(key, new ConfigurationHolder(builder));
186   }
187
188   /**
189    * Populate override configurtaion.
190    *
191    * @param key  the key
192    * @param file the file
193    * @throws Exception the exception
194    */
195   public void populateOverrideConfigurtaion(String key, File file) throws Exception {
196     ConfigurationHolder holder = store.get(key);
197     if (holder == null) {
198       if (dbAccessible) {
199         store.put(key,
200             holder = new ConfigurationHolder(ConfigurationUtils.getDbConfigurationBuilder(key)));
201       } else {
202         store.put(key, holder = new ConfigurationHolder(new CombinedConfiguration()));
203       }
204     }
205     holder.addOverrideConfiguration(file.getAbsolutePath(),
206         ConfigurationUtils.getConfigurationBuilder(file, true));
207     populateTenantsNamespace(key, true);
208   }
209
210   /**
211    * Refresh override configurtaion for.
212    *
213    * @param key   the key
214    * @param index the index
215    * @throws Exception the exception
216    */
217   public void refreshOverrideConfigurtaionFor(String key, int index) throws Exception {
218     ConfigurationHolder holder = store.get(key);
219     if (holder != null) {
220       holder.refreshOverrideConfiguration(index);
221     }
222   }
223
224   /**
225    * Remove override configurtaion.
226    *
227    * @param file the file
228    * @throws Exception the exception
229    */
230   public void removeOverrideConfigurtaion(File file) throws Exception {
231     Iterator<String> iterator = new ArrayList(store.keySet()).iterator();
232     while (iterator.hasNext()) {
233       ConfigurationHolder holder = store.get(iterator.next());
234       if (holder.containsOverrideConfiguration(file.getAbsolutePath())) {
235         holder.removeOverrideConfiguration(file.getAbsolutePath());
236       }
237     }
238
239   }
240
241   private class ConfigurationHolder {
242
243     /**
244      * The Builder.
245      */
246     BasicConfigurationBuilder<Configuration> builder;
247     /**
248      * The Last configuration build time.
249      */
250     Timestamp lastConfigurationBuildTime;
251     /**
252      * The Config.
253      */
254     Configuration config;
255     /**
256      * The Composite.
257      */
258     Configuration composite;
259     /**
260      * The Last config change timestamp.
261      */
262     Timestamp lastConfigChangeTimestamp;
263     private Map<String, FileBasedConfigurationBuilder<FileBasedConfiguration>>
264         overrideConfiguration = new LinkedHashMap<>();
265
266
267     /**
268      * Instantiates a new Configuration holder.
269      *
270      * @param builder the builder
271      */
272     public ConfigurationHolder(BasicConfigurationBuilder builder) {
273       this.builder = builder;
274     }
275
276     /**
277      * Instantiates a new Configuration holder.
278      *
279      * @param builder the builder
280      */
281     public ConfigurationHolder(Configuration builder) {
282       this.config = builder;
283     }
284
285     /**
286      * Refresh override configuration.
287      *
288      * @param index the index
289      */
290     public void refreshOverrideConfiguration(int index) {
291       int count = -1;
292       for (FileBasedConfigurationBuilder overrides : overrideConfiguration.values()) {
293         try {
294           if (++count == index) {
295             overrides.save();
296             overrides.resetResult();
297           }
298         } catch (ConfigurationException exception) {
299           //do nothing
300         }
301       }
302     }
303
304     /**
305      * Add override configuration.
306      *
307      * @param path    the path
308      * @param builder the builder
309      */
310     public void addOverrideConfiguration(String path,
311                                      BasicConfigurationBuilder<FileBasedConfiguration> builder) {
312       overrideConfiguration.put(path.toUpperCase(), (FileBasedConfigurationBuilder) builder);
313       getEffectiveConfiguration(config, overrideConfiguration.values());
314     }
315
316     /**
317      * Remove override configuration.
318      *
319      * @param path the path
320      */
321     public void removeOverrideConfiguration(String path) {
322       overrideConfiguration.remove(path.toUpperCase());
323       getEffectiveConfiguration(config, overrideConfiguration.values());
324     }
325
326     /**
327      * Contains override configuration boolean.
328      *
329      * @param path the path
330      * @return the boolean
331      */
332     public boolean containsOverrideConfiguration(String path) {
333       return overrideConfiguration.containsKey(path.toUpperCase());
334     }
335
336     /**
337      * Gets configuration.
338      *
339      * @param namespace the namespace
340      * @return the configuration
341      * @throws Exception the exception
342      */
343     public Configuration getConfiguration(String namespace) throws Exception {
344       if (config == null) {
345         config = builder.getConfiguration();
346         lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis());
347       } else if (lastConfigurationBuildTime != null
348           && System.currentTimeMillis() - lastConfigurationBuildTime.getTime()
349           > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
350                   .getInt("config.refresh.interval")) {
351         Timestamp temp = getLastUpdateTimestampFor(namespace);
352         if (temp != null) {
353           if (lastConfigChangeTimestamp == null
354               || temp.getTime() > lastConfigChangeTimestamp.getTime()) {
355             builder.resetResult();
356             config = builder.getConfiguration();
357             lastConfigChangeTimestamp = temp;
358             getEffectiveConfiguration(config, overrideConfiguration.values());
359           }
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         return composite = cc;
378       } catch (Exception exception) {
379         exception.printStackTrace();
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         exception.printStackTrace();
402       }
403
404       return timestamp;
405     }
406
407
408   }
409
410   public boolean isDBAccessible(){
411     return dbAccessible;
412   }
413
414
415 }