1 package org.onap.config.impl;
4 import org.apache.commons.configuration2.Configuration;
5 import org.apache.commons.configuration2.DatabaseConfiguration;
6 import org.onap.config.ConfigurationUtils;
7 import org.onap.config.Constants;
8 import org.onap.config.NonConfigResource;
9 import org.onap.config.api.Config;
10 import org.onap.config.api.ConfigurationChangeListener;
11 import org.onap.config.api.Hint;
14 import java.lang.reflect.Constructor;
15 import java.lang.reflect.Field;
16 import java.lang.reflect.Modifier;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collection;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.List;
26 import java.util.function.Predicate;
28 import static org.onap.config.ConfigurationUtils.getConfigurationRepositoryKey;
31 * The type Configuration.
33 public class ConfigurationImpl implements org.onap.config.api.Configuration {
35 private static ThreadLocal<String> tenant = new ThreadLocal<String>() {
36 protected String initialValue() {
37 return Constants.DEFAULT_TENANT;
42 private static boolean instantiated = false;
43 private static NonConfigResource nonConfigResource = NonConfigResource.create(propertyName -> System.getProperties().getProperty(propertyName));
45 * The Change notifier.
47 ConfigurationChangeNotifier changeNotifier;
50 * Instantiates a new Configuration.
52 * @throws Exception the exception
54 public ConfigurationImpl() throws Exception {
55 if (instantiated || !CliConfigurationImpl.class.isAssignableFrom(this.getClass())) {
56 throw new RuntimeException("Illegal access to configuration.");
58 Map<String, AggregateConfiguration> moduleConfigStore = new HashMap<>();
59 List<URL> classpathResources = ConfigurationUtils.getAllClassPathResources();
60 Predicate<URL> predicate = ConfigurationUtils::isConfig;
61 for (URL url : classpathResources) {
62 if (predicate.test(url)) {
63 String moduleName = ConfigurationUtils.getConfigurationRepositoryKey(url);
64 AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
65 if (moduleConfig == null) {
66 moduleConfig = new AggregateConfiguration();
67 moduleConfigStore.put(moduleName, moduleConfig);
69 moduleConfig.addConfig(url);
71 nonConfigResource.add(url);
74 String configLocation = System.getProperty("config.location");
75 if (configLocation != null && configLocation.trim().length() > 0) {
76 File root = new File(configLocation);
77 Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
78 Predicate<File> filePredicate = ConfigurationUtils::isConfig;
79 for (File file : filesystemResources) {
80 if (filePredicate.test(file)) {
81 String moduleName = ConfigurationUtils.getConfigurationRepositoryKey(file);
82 AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
83 if (moduleConfig == null) {
84 moduleConfig = new AggregateConfiguration();
85 moduleConfigStore.put(moduleName, moduleConfig);
87 moduleConfig.addConfig(file);
89 nonConfigResource.add(file);
93 String tenantConfigLocation = System.getProperty("tenant.config.location");
94 if (tenantConfigLocation != null && tenantConfigLocation.trim().length() > 0) {
95 File root = new File(tenantConfigLocation);
96 Collection<File> tenantsRoot = ConfigurationUtils.getAllFiles(root, false, true);
97 Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
98 Predicate<File> filePredicate = ConfigurationUtils::isConfig;
99 for (File file : filesystemResources) {
100 if (filePredicate.test(file)) {
101 String moduleName = ConfigurationUtils.getNamespace(file);
102 for (File tenanatFileRoot : tenantsRoot) {
103 if (file.getAbsolutePath().startsWith(tenanatFileRoot.getAbsolutePath())) {
104 moduleName = ConfigurationUtils.getConfigurationRepositoryKey(
105 (tenanatFileRoot.getName().toUpperCase() + Constants.TENANT_NAMESPACE_SAPERATOR
106 + moduleName).split(Constants.TENANT_NAMESPACE_SAPERATOR));
109 AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
110 if (moduleConfig == null) {
111 moduleConfig = new AggregateConfiguration();
112 moduleConfigStore.put(moduleName, moduleConfig);
114 moduleConfig.addConfig(file);
118 populateFinalConfigurationIncrementally(moduleConfigStore);
119 ConfigurationRepository.lookup().initTenantsAndNamespaces();
120 String nodeConfigLocation = System.getProperty("node.config.location");
121 if (nodeConfigLocation != null && nodeConfigLocation.trim().length() > 0) {
122 File root = new File(nodeConfigLocation);
123 Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
124 Predicate<File> filePredicate = ConfigurationUtils::isConfig;
125 for (File file : filesystemResources) {
126 if (filePredicate.test(file)) {
127 ConfigurationRepository.lookup().populateOverrideConfigurtaion(
128 ConfigurationUtils.getConfigurationRepositoryKey(ConfigurationUtils.getNamespace(file)
129 .split(Constants.TENANT_NAMESPACE_SAPERATOR)), file);
134 changeNotifier = new ConfigurationChangeNotifier(moduleConfigStore);
138 public void addConfigurationChangeListener(String tenant, String namespace, String key,
139 ConfigurationChangeListener myself) {
140 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
141 : Constants.DEFAULT_TENANT;
143 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
144 : Constants.DEFAULT_NAMESPACE;
145 if (key == null || key.trim().length() == 0) {
146 throw new IllegalArgumentException("Key can't be null.");
148 if (myself == null) {
149 throw new IllegalArgumentException("ConfigurationChangeListener instance is null.");
152 changeNotifier.notifyChangesTowards(tenant, namespace, key, myself);
153 } catch (Exception exception) {
154 exception.printStackTrace();
158 private void populateFinalConfigurationIncrementally(Map<String, AggregateConfiguration> configs)
160 boolean isDbAccessible = false;
162 Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE)
164 ConfigurationRepository.lookup().populateConfigurtaion(
165 Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE,
167 Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE)
168 .getFinalConfiguration());
169 isDbAccessible = ConfigurationUtils.executeDdlSql(ConfigurationRepository.lookup()
170 .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
171 .getString("createtablecql"));
172 if (isDbAccessible) {
173 ConfigurationUtils.executeDdlSql(ConfigurationRepository.lookup()
174 .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
175 .getString("createmonitoringtablecql"));
179 Set<String> modules = configs.keySet();
180 for (String module : modules) {
181 if (isDbAccessible) {
182 DatabaseConfiguration config =
183 ConfigurationUtils.getDbConfigurationBuilder(module).getConfiguration();
184 Configuration currentConfig = configs.get(module).getFinalConfiguration();
185 Iterator<String> keys = currentConfig.getKeys();
186 while (keys.hasNext()) {
187 String currentKey = keys.next();
188 if (!(Constants.MODE_KEY.equals(currentKey)
189 || Constants.NAMESPACE_KEY.equals(currentKey)
190 || Constants.LOAD_ORDER_KEY.equals(currentKey))) {
191 if (!config.containsKey(currentKey)) {
192 Object propValue = currentConfig.getProperty(currentKey);
193 if (propValue instanceof Collection) {
194 config.addProperty(currentKey, propValue.toString());
196 config.addProperty(currentKey, propValue);
202 ConfigurationRepository.lookup()
203 .populateConfigurtaion(module, configs.get(module).getFinalConfiguration());
209 public <T> T get(String tenant, String namespace, String key, Class<T> clazz, Hint... hints) {
211 String[] tenantNamespaceArrayy;
212 if (tenant == null && namespace != null) {
213 tenantNamespaceArrayy = namespace.split(Constants.TENANT_NAMESPACE_SAPERATOR);
214 if (tenantNamespaceArrayy.length > 1) {
215 tenant = tenantNamespaceArrayy[0];
216 namespace = tenantNamespaceArrayy[1];
220 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
221 : Constants.DEFAULT_TENANT;
223 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
224 : Constants.DEFAULT_NAMESPACE;
225 T returnValue = null;
226 returnValue = (T) getInternal(tenant, namespace, key,
227 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
228 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
230 if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
231 && !Constants.DEFAULT_TENANT.equals(tenant)) {
232 returnValue = (T) getInternal(Constants.DEFAULT_TENANT, namespace, key,
233 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
234 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
237 if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
238 && !Constants.DEFAULT_NAMESPACE.equals(namespace)) {
239 returnValue = (T) getInternal(tenant, Constants.DEFAULT_NAMESPACE, key,
240 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
241 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
244 if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
245 && !Constants.DEFAULT_NAMESPACE.equals(namespace)
246 && !Constants.DEFAULT_TENANT.equals(tenant)) {
247 returnValue = (T) getInternal(Constants.DEFAULT_TENANT, Constants.DEFAULT_NAMESPACE, key,
248 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
249 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
252 if (returnValue == null && clazz.isPrimitive()) {
253 return (T) ConfigurationUtils.getDefaultFor(clazz);
263 * @param <T> the type parameter
264 * @param tenant the tenant
265 * @param namespace the namespace
267 * @param clazz the clazz
268 * @param hints the hints
269 * @return the internal
271 protected <T> T getInternal(String tenant, String namespace, String key, Class<T> clazz,
273 int processingHints = Hint.DEFAULT.value();
275 for (Hint hint : hints) {
276 processingHints = processingHints | hint.value();
280 if (tenant == null || tenant.trim().length() == 0) {
281 tenant = this.tenant.get();
283 tenant = tenant.toUpperCase();
285 if (namespace == null || namespace.trim().length() == 0) {
286 namespace = Constants.DEFAULT_NAMESPACE;
288 namespace = namespace.toUpperCase();
290 if (key == null || key.trim().length() == 0) {
291 if (!clazz.isAnnotationPresent(Config.class)) {
292 throw new IllegalArgumentException("Key can't be null.");
296 throw new IllegalArgumentException("clazz is null.");
298 if (clazz.isPrimitive()) {
299 clazz = getWrapperClass(clazz);
302 if (ConfigurationUtils.isWrapperClass(clazz) || clazz.isPrimitive()) {
305 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
306 key, processingHints);
308 if (ConfigurationUtils.isCollection(obj.toString())) {
309 obj = ConfigurationUtils.getCollectionString(obj.toString());
311 String value = obj.toString().split(",")[0];
312 value = ConfigurationUtils.processVariablesIfPresent(tenant, namespace, value);
313 return (T) getValue(value, clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
318 } else if (clazz.isArray()
319 && (clazz.getComponentType().isPrimitive() || ConfigurationUtils.isWrapperClass(clazz.getComponentType()))) {
322 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
323 key, processingHints);
325 Class componentClass = clazz.getComponentType();
326 if (clazz.getComponentType().isPrimitive()) {
327 componentClass = getWrapperClass(clazz.getComponentType());
329 String collString = ConfigurationUtils.getCollectionString(obj.toString());
330 ArrayList<String> tempCollection = new ArrayList<>();
331 for (String itemValue : collString.split(",")) {
333 .add(ConfigurationUtils.processVariablesIfPresent(tenant, namespace, itemValue));
335 Collection<T> collection = convert(
336 ConfigurationUtils.getCollectionString(Arrays.toString(tempCollection.toArray())),
337 componentClass, processingHints);
338 if (clazz.getComponentType().isPrimitive()) {
339 return (T) ConfigurationUtils.getPrimitiveArray(collection, clazz.getComponentType());
341 return (T) collection
342 .toArray(getZeroLengthArrayFor(getWrapperClass(clazz.getComponentType())));
347 } else if (clazz.isAnnotationPresent(Config.class)) {
348 return read(tenant, namespace, clazz,
349 (key == null || key.trim().length() == 0) ? "" : (key + "."), hints);
351 throw new IllegalArgumentException(
352 "Only pimitive classes, wrapper classes, corresponding array classes and any "
353 + "class decorated with @org.openecomp.config.api.Config are allowed as argument.");
355 } catch (Exception exception) {
356 exception.printStackTrace();
362 private <T> T read(String tenant, String namespace, Class<T> clazz, String keyPrefix,
363 Hint... hints) throws Exception {
365 clazz.getAnnotation(Config.class);
366 if (confAnnot != null && confAnnot.key().length()>0 && !keyPrefix.endsWith(".")) {
367 keyPrefix += (confAnnot.key() + ".");
369 Constructor<T> constructor = clazz.getDeclaredConstructor();
370 constructor.setAccessible(true);
371 T objToReturn = constructor.newInstance();
372 for (Field field : clazz.getDeclaredFields()) {
373 field.setAccessible(true);
374 Config fieldConfAnnot =
375 field.getAnnotation(Config.class);
376 if (fieldConfAnnot != null) {
377 if (field.getType().isPrimitive() || ConfigurationUtils.isWrapperClass(field.getType())
378 || (field.getType().isArray() && (field.getType().getComponentType().isPrimitive()
379 || ConfigurationUtils.isWrapperClass(field.getType().getComponentType())))
380 || field.getType().getAnnotation(Config.class) != null) {
381 field.set(objToReturn,
382 get(tenant, namespace, keyPrefix + fieldConfAnnot.key(), field.getType(), hints));
383 } else if (Collection.class.isAssignableFrom(field.getType())) {
384 Object obj = get(tenant, namespace, keyPrefix + fieldConfAnnot.key(),
385 ConfigurationUtils.getArrayClass(ConfigurationUtils.getCollectionGenericType(field)),
388 List list = Arrays.asList((Object[]) obj);
389 Class clazzToInstantiate = null;
390 if (field.getType().isInterface()) {
392 ConfigurationUtils.getConcreteCollection(field.getType()).getClass();
393 } else if (Modifier.isAbstract(field.getType().getModifiers())) {
395 ConfigurationUtils.getCompatibleCollectionForAbstractDef(field.getType())
398 clazzToInstantiate = field.getType();
400 Constructor construct =
401 getConstructorWithArguments(clazzToInstantiate, Collection.class);
402 if (construct != null) {
403 construct.setAccessible(true);
404 field.set(objToReturn, construct.newInstance(list));
405 } else if ((construct =
406 getConstructorWithArguments(clazzToInstantiate, Integer.class, Boolean.class,
407 Collection.class)) != null) {
408 construct.setAccessible(true);
409 field.set(objToReturn, construct.newInstance(list.size(), true, list));
412 }else if (Map.class.isAssignableFrom(field.getType())){
413 field.set(objToReturn, generateMap(tenant, namespace, keyPrefix+fieldConfAnnot.key()));
420 private Constructor getConstructorWithArguments(Class clazz, Class... classes) {
422 return clazz.getDeclaredConstructor(classes);
423 } catch (Exception exception) {
428 private Class getWrapperClass(Class clazz) {
429 if (byte.class == clazz) {
431 } else if (short.class == clazz) {
433 } else if (int.class == clazz) {
434 return Integer.class;
435 } else if (long.class == clazz) {
437 } else if (float.class == clazz) {
439 } else if (double.class == clazz) {
441 } else if (char.class == clazz) {
442 return Character.class;
443 } else if (boolean.class == clazz) {
444 return Boolean.class;
449 private <T> T getValue(Object obj, Class<T> clazz, int processingHint) {
450 if (obj == null || obj.toString().trim().length() == 0) {
453 obj = obj.toString().trim();
455 if (String.class.equals(clazz)) {
456 if (obj.toString().startsWith("@") && ConfigurationUtils.isExternalLookup(processingHint)) {
457 String contents = ConfigurationUtils
458 .getFileContents(nonConfigResource.locate(obj.toString().substring(1).trim()));
459 if (contents == null) {
460 contents = ConfigurationUtils.getFileContents(obj.toString().substring(1).trim());
462 if (contents != null) {
466 return (T) obj.toString();
467 } else if (Number.class.isAssignableFrom(clazz)) {
468 Double doubleValue = Double.valueOf(obj.toString());
469 switch (clazz.getName()) {
470 case "java.lang.Byte":
471 Byte byteVal = doubleValue.byteValue();
473 case "java.lang.Short":
474 Short shortVal = doubleValue.shortValue();
476 case "java.lang.Integer":
477 Integer intVal = doubleValue.intValue();
479 case "java.lang.Long":
480 Long longVal = doubleValue.longValue();
482 case "java.lang.Float":
483 Float floatVal = doubleValue.floatValue();
485 case "java.lang.Double":
486 Double doubleVal = doubleValue.doubleValue();
487 return (T) doubleVal;
490 } else if (Boolean.class.equals(clazz)) {
491 return (T) Boolean.valueOf(obj.toString());
492 } else if (Character.class.equals(clazz)) {
493 return (T) Character.valueOf(obj.toString().charAt(0));
498 private <T> T[] getZeroLengthArrayFor(Class<T> clazz) {
500 if (clazz == int.class) {
502 } else if (clazz == byte.class) {
504 } else if (clazz == short.class) {
506 } else if (clazz == long.class) {
508 } else if (clazz == float.class) {
510 } else if (clazz == double.class) {
511 obj = new double[]{};
512 } else if (clazz == boolean.class) {
513 obj = new boolean[]{};
514 } else if (clazz == char.class) {
516 } else if (clazz == Byte.class) {
518 } else if (clazz == Short.class) {
520 } else if (clazz == Integer.class) {
521 obj = new Integer[]{};
522 } else if (clazz == Long.class) {
524 } else if (clazz == Float.class) {
526 } else if (clazz == Double.class) {
527 obj = new Double[]{};
528 } else if (clazz == Boolean.class) {
529 obj = new Boolean[]{};
530 } else if (clazz == Character.class) {
531 obj = new Character[]{};
532 } else if (clazz == String.class) {
533 obj = new String[]{};
538 private <T> Collection<T> convert(String commaSaperatedValues, Class<T> clazz,
539 int processingHints) {
540 ArrayList<T> collection = new ArrayList<>();
541 for (String value : commaSaperatedValues.split(",")) {
543 T type1 = getValue(value, clazz, processingHints);
545 collection.add(type1);
547 } catch (RuntimeException re) {
557 public void shutdown() {
558 if (changeNotifier != null) {
560 changeNotifier.shutdown();
561 ConfigurationDataSource.lookup().close();
562 } catch (Exception exception) {
563 exception.printStackTrace();
569 public void removeConfigurationChangeListener(String tenant, String namespace, String key,
570 ConfigurationChangeListener myself) {
571 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
572 : Constants.DEFAULT_TENANT;
574 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
575 : Constants.DEFAULT_NAMESPACE;
576 if (key == null || key.trim().length() == 0) {
577 throw new IllegalArgumentException("Key can't be null.");
580 changeNotifier.stopNotificationTowards(tenant, namespace, key, myself);
581 } catch (Exception exception) {
582 exception.printStackTrace();
587 public <T> Map<String, T> populateMap(String tenantId, String namespace, String key, Class<T> clazz){
588 if (tenantId==null || tenantId.trim().length()==0){
589 tenantId = this.tenant.get();
591 tenantId = tenantId.toUpperCase();
593 if (namespace==null || namespace.trim().length()==0){
594 namespace = Constants.DEFAULT_NAMESPACE;
596 namespace = namespace.toUpperCase();
598 Map<String, T> map = new HashMap<>();
599 Iterator<String> keys ;
601 if (ConfigurationRepository.lookup().isDBAccessible()){
602 keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor(
603 Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+ Constants.KEY_ELEMENTS_DELEMETER+namespace}).iterator();
605 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
607 while(keys.hasNext()){
608 String k = keys.next();
609 if (k.startsWith(key+".")){
610 k = k.substring(key.length()+1);
611 String subkey = k.substring(0, k.indexOf("."));
612 if (!map.containsKey(subkey)){
613 map.put(subkey, get(tenantId, namespace, key+"."+subkey, clazz));
617 }catch (Exception e){
624 public Map generateMap(String tenantId, String namespace, String key){
625 if (tenantId==null || tenantId.trim().length()==0){
626 tenantId = this.tenant.get();
628 tenantId = tenantId.toUpperCase();
630 if (namespace==null || namespace.trim().length()==0){
631 namespace = Constants.DEFAULT_NAMESPACE;
633 namespace = namespace.toUpperCase();
635 Map map, parentMap = new HashMap<>();
636 Iterator<String> keys ;
638 if (ConfigurationRepository.lookup().isDBAccessible()){
639 keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor(
640 Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+ Constants.KEY_ELEMENTS_DELEMETER+namespace}).iterator();
642 if (key==null || key.trim().length()==0){
643 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys();
645 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
648 while(keys.hasNext()){
650 String k = keys.next();
652 if (key!=null && key.trim().length()!=0 && !k.startsWith(key+".")){
655 String value = getAsString(tenantId, namespace, k);
656 if (key!=null && key.trim().length()!=0 && k.startsWith(key+".")){
657 k = k.substring(key.trim().length()+1);
660 while(k.contains(".")){
661 if (k.contains(".")){
662 String subkey = k.substring(0, k.indexOf("."));
663 k = k.substring(k.indexOf(".")+1);
664 if (!map.containsKey(subkey)){
665 map.put(subkey, map=new HashMap<>());
667 map = (Map)map.get(subkey);
673 }catch (Exception e){