1 package org.onap.config.impl;
3 import static org.onap.config.ConfigurationUtils.getConfigurationRepositoryKey;
5 import org.apache.commons.configuration2.Configuration;
6 import org.apache.commons.configuration2.DatabaseConfiguration;
7 import org.onap.config.ConfigurationUtils;
8 import org.onap.config.Constants;
9 import org.onap.config.NonConfigResource;
10 import org.onap.config.api.Config;
11 import org.onap.config.api.ConfigurationChangeListener;
12 import org.onap.config.api.Hint;
15 import java.lang.reflect.Constructor;
16 import java.lang.reflect.Field;
17 import java.lang.reflect.Modifier;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collection;
22 import java.util.HashMap;
23 import java.util.Iterator;
24 import java.util.List;
27 import java.util.function.Predicate;
30 * The type Configuration.
32 public class ConfigurationImpl implements org.onap.config.api.Configuration {
34 private static ThreadLocal<String> tenant = new ThreadLocal<String>() {
35 protected String initialValue() {
36 return Constants.DEFAULT_TENANT;
41 private static boolean instantiated = false;
43 * The Change notifier.
45 ConfigurationChangeNotifier changeNotifier;
48 * Instantiates a new Configuration.
50 * @throws Exception the exception
52 public ConfigurationImpl() throws Exception {
53 if (instantiated || !CliConfigurationImpl.class.isAssignableFrom(this.getClass())) {
54 throw new RuntimeException("Illegal access to configuration.");
56 Map<String, AggregateConfiguration> moduleConfigStore = new HashMap<>();
57 List<URL> classpathResources = ConfigurationUtils.getAllClassPathResources();
58 Predicate<URL> predicate = ConfigurationUtils::isConfig;
59 for (URL url : classpathResources) {
60 if (predicate.test(url)) {
61 String moduleName = ConfigurationUtils.getConfigurationRepositoryKey(url);
62 AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
63 if (moduleConfig == null) {
64 moduleConfig = new AggregateConfiguration();
65 moduleConfigStore.put(moduleName, moduleConfig);
67 moduleConfig.addConfig(url);
69 NonConfigResource.add(url);
72 String configLocation = System.getProperty("config.location");
73 if (configLocation != null && configLocation.trim().length() > 0) {
74 File root = new File(configLocation);
75 Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
76 Predicate<File> filePredicate = ConfigurationUtils::isConfig;
77 for (File file : filesystemResources) {
78 if (filePredicate.test(file)) {
79 String moduleName = ConfigurationUtils.getConfigurationRepositoryKey(file);
80 AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
81 if (moduleConfig == null) {
82 moduleConfig = new AggregateConfiguration();
83 moduleConfigStore.put(moduleName, moduleConfig);
85 moduleConfig.addConfig(file);
87 NonConfigResource.add(file);
91 String tenantConfigLocation = System.getProperty("tenant.config.location");
92 if (tenantConfigLocation != null && tenantConfigLocation.trim().length() > 0) {
93 File root = new File(tenantConfigLocation);
94 Collection<File> tenantsRoot = ConfigurationUtils.getAllFiles(root, false, true);
95 Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
96 Predicate<File> filePredicate = ConfigurationUtils::isConfig;
97 for (File file : filesystemResources) {
98 if (filePredicate.test(file)) {
99 String moduleName = ConfigurationUtils.getNamespace(file);
100 for (File tenanatFileRoot : tenantsRoot) {
101 if (file.getAbsolutePath().startsWith(tenanatFileRoot.getAbsolutePath())) {
102 moduleName = ConfigurationUtils.getConfigurationRepositoryKey(
103 (tenanatFileRoot.getName().toUpperCase() + Constants.TENANT_NAMESPACE_SAPERATOR
104 + moduleName).split(Constants.TENANT_NAMESPACE_SAPERATOR));
107 AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
108 if (moduleConfig == null) {
109 moduleConfig = new AggregateConfiguration();
110 moduleConfigStore.put(moduleName, moduleConfig);
112 moduleConfig.addConfig(file);
116 populateFinalConfigurationIncrementally(moduleConfigStore);
117 ConfigurationRepository.lookup().initTenantsAndNamespaces();
118 String nodeConfigLocation = System.getProperty("node.config.location");
119 if (nodeConfigLocation != null && nodeConfigLocation.trim().length() > 0) {
120 File root = new File(nodeConfigLocation);
121 Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
122 Predicate<File> filePredicate = ConfigurationUtils::isConfig;
123 for (File file : filesystemResources) {
124 if (filePredicate.test(file)) {
125 ConfigurationRepository.lookup().populateOverrideConfigurtaion(
126 ConfigurationUtils.getConfigurationRepositoryKey(ConfigurationUtils.getNamespace(file)
127 .split(Constants.TENANT_NAMESPACE_SAPERATOR)), file);
132 changeNotifier = new ConfigurationChangeNotifier(moduleConfigStore);
136 public void addConfigurationChangeListener(String tenant, String namespace, String key,
137 ConfigurationChangeListener myself) {
138 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
139 : Constants.DEFAULT_TENANT;
141 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
142 : Constants.DEFAULT_NAMESPACE;
143 if (key == null || key.trim().length() == 0) {
144 throw new IllegalArgumentException("Key can't be null.");
146 if (myself == null) {
147 throw new IllegalArgumentException("ConfigurationChangeListener instance is null.");
150 changeNotifier.notifyChangesTowards(tenant, namespace, key, myself);
151 } catch (Exception exception) {
152 exception.printStackTrace();
156 private void populateFinalConfigurationIncrementally(Map<String, AggregateConfiguration> configs)
158 boolean isDbAccessible = false;
160 Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE)
162 ConfigurationRepository.lookup().populateConfigurtaion(
163 Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE,
165 Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE)
166 .getFinalConfiguration());
167 isDbAccessible = ConfigurationUtils.executeDdlSql(ConfigurationRepository.lookup()
168 .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
169 .getString("createtablecql"));
170 if (isDbAccessible) {
171 ConfigurationUtils.executeDdlSql(ConfigurationRepository.lookup()
172 .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
173 .getString("createmonitoringtablecql"));
177 Set<String> modules = configs.keySet();
178 for (String module : modules) {
179 if (isDbAccessible) {
180 DatabaseConfiguration config =
181 ConfigurationUtils.getDbConfigurationBuilder(module).getConfiguration();
182 Configuration currentConfig = configs.get(module).getFinalConfiguration();
183 Iterator<String> keys = currentConfig.getKeys();
184 while (keys.hasNext()) {
185 String currentKey = keys.next();
186 if (!(Constants.MODE_KEY.equals(currentKey)
187 || Constants.NAMESPACE_KEY.equals(currentKey)
188 || Constants.LOAD_ORDER_KEY.equals(currentKey))) {
189 if (!config.containsKey(currentKey)) {
190 Object propValue = currentConfig.getProperty(currentKey);
191 if (propValue instanceof Collection) {
192 config.addProperty(currentKey, propValue.toString());
194 config.addProperty(currentKey, propValue);
200 ConfigurationRepository.lookup()
201 .populateConfigurtaion(module, configs.get(module).getFinalConfiguration());
207 public <T> T get(String tenant, String namespace, String key, Class<T> clazz, Hint... hints) {
209 String[] tenantNamespaceArrayy = null;
210 if (tenant == null && namespace != null
211 && (tenantNamespaceArrayy = namespace.split(Constants.TENANT_NAMESPACE_SAPERATOR)).length
213 tenant = tenantNamespaceArrayy[0];
214 namespace = tenantNamespaceArrayy[1];
217 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
218 : Constants.DEFAULT_TENANT;
220 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
221 : Constants.DEFAULT_NAMESPACE;
222 T returnValue = null;
223 returnValue = (T) getInternal(tenant, namespace, key,
224 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
225 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
227 if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
228 && !Constants.DEFAULT_TENANT.equals(tenant)) {
229 returnValue = (T) getInternal(Constants.DEFAULT_TENANT, namespace, key,
230 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
231 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
234 if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
235 && !Constants.DEFAULT_NAMESPACE.equals(namespace)) {
236 returnValue = (T) getInternal(tenant, Constants.DEFAULT_NAMESPACE, key,
237 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
238 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
241 if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
242 && !Constants.DEFAULT_NAMESPACE.equals(namespace)
243 && !Constants.DEFAULT_TENANT.equals(tenant)) {
244 returnValue = (T) getInternal(Constants.DEFAULT_TENANT, Constants.DEFAULT_NAMESPACE, key,
245 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
246 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
249 if (returnValue == null && clazz.isPrimitive()) {
250 return (T) ConfigurationUtils.getDefaultFor(clazz);
260 * @param <T> the type parameter
261 * @param tenant the tenant
262 * @param namespace the namespace
264 * @param clazz the clazz
265 * @param hints the hints
266 * @return the internal
268 protected <T> T getInternal(String tenant, String namespace, String key, Class<T> clazz,
270 int processingHints = Hint.DEFAULT.value();
272 for (Hint hint : hints) {
273 processingHints = processingHints | hint.value();
277 if (tenant == null || tenant.trim().length() == 0) {
278 tenant = this.tenant.get();
280 tenant = tenant.toUpperCase();
282 if (namespace == null || namespace.trim().length() == 0) {
283 namespace = Constants.DEFAULT_NAMESPACE;
285 namespace = namespace.toUpperCase();
287 if (key == null || key.trim().length() == 0) {
288 if (!clazz.isAnnotationPresent(Config.class)) {
289 throw new IllegalArgumentException("Key can't be null.");
293 throw new IllegalArgumentException("clazz is null.");
295 if (clazz.isPrimitive()) {
296 clazz = getWrapperClass(clazz);
299 if (ConfigurationUtils.isWrapperClass(clazz) || clazz.isPrimitive()) {
302 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
303 key, processingHints);
305 if (ConfigurationUtils.isCollection(obj.toString())) {
306 obj = ConfigurationUtils.getCollectionString(obj.toString());
308 String value = obj.toString().split(",")[0];
309 value = ConfigurationUtils.processVariablesIfPresent(tenant, namespace, value);
310 return (T) getValue(value, clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
315 } else if (clazz.isArray()
316 && (clazz.getComponentType().isPrimitive() || ConfigurationUtils.isWrapperClass(clazz.getComponentType()))) {
319 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
320 key, processingHints);
322 Class componentClass = clazz.getComponentType();
323 if (clazz.getComponentType().isPrimitive()) {
324 componentClass = getWrapperClass(clazz.getComponentType());
326 String collString = ConfigurationUtils.getCollectionString(obj.toString());
327 ArrayList<String> tempCollection = new ArrayList<>();
328 for (String itemValue : collString.split(",")) {
330 .add(ConfigurationUtils.processVariablesIfPresent(tenant, namespace, itemValue));
332 Collection<T> collection = convert(
333 ConfigurationUtils.getCollectionString(Arrays.toString(tempCollection.toArray())),
334 componentClass, processingHints);
335 if (clazz.getComponentType().isPrimitive()) {
336 return (T) ConfigurationUtils.getPrimitiveArray(collection, clazz.getComponentType());
338 return (T) collection
339 .toArray(getZeroLengthArrayFor(getWrapperClass(clazz.getComponentType())));
344 } else if (clazz.isAnnotationPresent(Config.class)) {
345 return read(tenant, namespace, clazz,
346 (key == null || key.trim().length() == 0) ? "" : (key + "."), hints);
348 throw new IllegalArgumentException(
349 "Only pimitive classes, wrapper classes, corresponding array classes and any "
350 + "class decorated with @org.openecomp.config.api.Config are allowed as argument.");
352 } catch (Exception exception) {
353 exception.printStackTrace();
359 private <T> T read(String tenant, String namespace, Class<T> clazz, String keyPrefix,
360 Hint... hints) throws Exception {
362 clazz.getAnnotation(Config.class);
363 if (confAnnot != null && confAnnot.key().length()>0 && !keyPrefix.endsWith(".")) {
364 keyPrefix += (confAnnot.key() + ".");
366 Constructor<T> constructor = clazz.getDeclaredConstructor();
367 constructor.setAccessible(true);
368 T objToReturn = constructor.newInstance();
369 for (Field field : clazz.getDeclaredFields()) {
370 field.setAccessible(true);
371 Config fieldConfAnnot =
372 field.getAnnotation(Config.class);
373 if (fieldConfAnnot != null) {
374 if (field.getType().isPrimitive() || ConfigurationUtils.isWrapperClass(field.getType())
375 || (field.getType().isArray() && (field.getType().getComponentType().isPrimitive()
376 || ConfigurationUtils.isWrapperClass(field.getType().getComponentType())))
377 || field.getType().getAnnotation(Config.class) != null) {
378 field.set(objToReturn,
379 get(tenant, namespace, keyPrefix + fieldConfAnnot.key(), field.getType(), hints));
380 } else if (Collection.class.isAssignableFrom(field.getType())) {
381 Object obj = get(tenant, namespace, keyPrefix + fieldConfAnnot.key(),
382 ConfigurationUtils.getArrayClass(ConfigurationUtils.getCollectionGenericType(field)),
385 List list = Arrays.asList((Object[]) obj);
386 Class clazzToInstantiate = null;
387 if (field.getType().isInterface()) {
389 ConfigurationUtils.getConcreteCollection(field.getType()).getClass();
390 } else if (Modifier.isAbstract(field.getType().getModifiers())) {
392 ConfigurationUtils.getCompatibleCollectionForAbstractDef(field.getType())
395 clazzToInstantiate = field.getType();
397 Constructor construct =
398 getConstructorWithArguments(clazzToInstantiate, Collection.class);
399 if (construct != null) {
400 construct.setAccessible(true);
401 field.set(objToReturn, construct.newInstance(list));
402 } else if ((construct =
403 getConstructorWithArguments(clazzToInstantiate, Integer.class, Boolean.class,
404 Collection.class)) != null) {
405 construct.setAccessible(true);
406 field.set(objToReturn, construct.newInstance(list.size(), true, list));
409 }else if (Map.class.isAssignableFrom(field.getType())){
410 field.set(objToReturn, generateMap(tenant, namespace, keyPrefix+fieldConfAnnot.key()));
417 private Constructor getConstructorWithArguments(Class clazz, Class... classes) {
419 return clazz.getDeclaredConstructor(classes);
420 } catch (Exception exception) {
425 private Class getWrapperClass(Class clazz) {
426 if (byte.class == clazz) {
428 } else if (short.class == clazz) {
430 } else if (int.class == clazz) {
431 return Integer.class;
432 } else if (long.class == clazz) {
434 } else if (float.class == clazz) {
436 } else if (double.class == clazz) {
438 } else if (char.class == clazz) {
439 return Character.class;
440 } else if (boolean.class == clazz) {
441 return Boolean.class;
446 private <T> T getValue(Object obj, Class<T> clazz, int processingHint) {
447 if (obj == null || obj.toString().trim().length() == 0) {
450 obj = obj.toString().trim();
452 if (String.class.equals(clazz)) {
453 if (obj.toString().startsWith("@") && ConfigurationUtils.isExternalLookup(processingHint)) {
454 String contents = ConfigurationUtils
455 .getFileContents(NonConfigResource.locate(obj.toString().substring(1).trim()));
456 if (contents == null) {
457 contents = ConfigurationUtils.getFileContents(obj.toString().substring(1).trim());
459 if (contents != null) {
463 return (T) obj.toString();
464 } else if (Number.class.isAssignableFrom(clazz)) {
465 Double doubleValue = Double.valueOf(obj.toString());
466 switch (clazz.getName()) {
467 case "java.lang.Byte":
468 Byte byteVal = doubleValue.byteValue();
470 case "java.lang.Short":
471 Short shortVal = doubleValue.shortValue();
473 case "java.lang.Integer":
474 Integer intVal = doubleValue.intValue();
476 case "java.lang.Long":
477 Long longVal = doubleValue.longValue();
479 case "java.lang.Float":
480 Float floatVal = doubleValue.floatValue();
482 case "java.lang.Double":
483 Double doubleVal = doubleValue.doubleValue();
484 return (T) doubleVal;
487 } else if (Boolean.class.equals(clazz)) {
488 return (T) Boolean.valueOf(obj.toString());
489 } else if (Character.class.equals(clazz)) {
490 return (T) Character.valueOf(obj.toString().charAt(0));
495 private <T> T[] getZeroLengthArrayFor(Class<T> clazz) {
497 if (clazz == int.class) {
499 } else if (clazz == byte.class) {
501 } else if (clazz == short.class) {
503 } else if (clazz == long.class) {
505 } else if (clazz == float.class) {
507 } else if (clazz == double.class) {
508 obj = new double[]{};
509 } else if (clazz == boolean.class) {
510 obj = new boolean[]{};
511 } else if (clazz == char.class) {
513 } else if (clazz == Byte.class) {
515 } else if (clazz == Short.class) {
517 } else if (clazz == Integer.class) {
518 obj = new Integer[]{};
519 } else if (clazz == Long.class) {
521 } else if (clazz == Float.class) {
523 } else if (clazz == Double.class) {
524 obj = new Double[]{};
525 } else if (clazz == Boolean.class) {
526 obj = new Boolean[]{};
527 } else if (clazz == Character.class) {
528 obj = new Character[]{};
529 } else if (clazz == String.class) {
530 obj = new String[]{};
535 private <T> Collection<T> convert(String commaSaperatedValues, Class<T> clazz,
536 int processingHints) {
537 ArrayList<T> collection = new ArrayList<>();
538 for (String value : commaSaperatedValues.split(",")) {
540 T type1 = getValue(value, clazz, processingHints);
542 collection.add(type1);
544 } catch (RuntimeException re) {
554 public void shutdown() {
555 if (changeNotifier != null) {
557 changeNotifier.shutdown();
558 ConfigurationDataSource.lookup().close();
559 } catch (Exception exception) {
560 exception.printStackTrace();
566 public void removeConfigurationChangeListener(String tenant, String namespace, String key,
567 ConfigurationChangeListener myself) {
568 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
569 : Constants.DEFAULT_TENANT;
571 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
572 : Constants.DEFAULT_NAMESPACE;
573 if (key == null || key.trim().length() == 0) {
574 throw new IllegalArgumentException("Key can't be null.");
577 changeNotifier.stopNotificationTowards(tenant, namespace, key, myself);
578 } catch (Exception exception) {
579 exception.printStackTrace();
584 public <T> Map<String, T> populateMap(String tenantId, String namespace, String key, Class<T> clazz){
585 if (tenantId==null || tenantId.trim().length()==0){
586 tenantId = this.tenant.get();
588 tenantId = tenantId.toUpperCase();
590 if (namespace==null || namespace.trim().length()==0){
591 namespace = Constants.DEFAULT_NAMESPACE;
593 namespace = namespace.toUpperCase();
595 Map<String, T> map = new HashMap<>();
596 Iterator<String> keys ;
598 if (ConfigurationRepository.lookup().isDBAccessible()){
599 keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor(
600 Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+ Constants.KEY_ELEMENTS_DELEMETER+namespace}).iterator();
602 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
604 while(keys.hasNext()){
605 String k = keys.next();
606 if (k.startsWith(key+".")){
607 k = k.substring(key.length()+1);
608 String subkey = k.substring(0, k.indexOf("."));
609 if (!map.containsKey(subkey)){
610 map.put(subkey, get(tenantId, namespace, key+"."+subkey, clazz));
614 }catch (Exception e){
621 public Map generateMap(String tenantId, String namespace, String key){
622 if (tenantId==null || tenantId.trim().length()==0){
623 tenantId = this.tenant.get();
625 tenantId = tenantId.toUpperCase();
627 if (namespace==null || namespace.trim().length()==0){
628 namespace = Constants.DEFAULT_NAMESPACE;
630 namespace = namespace.toUpperCase();
632 Map map, parentMap = new HashMap<>();
633 Iterator<String> keys ;
635 if (ConfigurationRepository.lookup().isDBAccessible()){
636 keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor(
637 Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+ Constants.KEY_ELEMENTS_DELEMETER+namespace}).iterator();
639 if (key==null || key.trim().length()==0){
640 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys();
642 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
645 while(keys.hasNext()){
647 String k = keys.next();
649 if (key!=null && key.trim().length()!=0 && !k.startsWith(key+".")){
652 String value = getAsString(tenantId, namespace, k);
653 if (key!=null && key.trim().length()!=0 && k.startsWith(key+".")){
654 k = k.substring(key.trim().length()+1);
657 while(k.contains(".")){
658 if (k.contains(".")){
659 String subkey = k.substring(0, k.indexOf("."));
660 k = k.substring(k.indexOf(".")+1);
661 if (!map.containsKey(subkey)){
662 map.put(subkey, map=new HashMap<>());
664 map = (Map)map.get(subkey);
670 }catch (Exception e){