1 package org.onap.config.impl;
3 import org.apache.commons.configuration2.Configuration;
4 import org.apache.commons.configuration2.DatabaseConfiguration;
5 import org.onap.config.ConfigurationUtils;
6 import org.onap.config.Constants;
7 import org.onap.config.NonConfigResource;
8 import org.onap.config.api.Config;
9 import org.onap.config.api.ConfigurationChangeListener;
10 import org.onap.config.api.Hint;
13 import java.lang.reflect.Constructor;
14 import java.lang.reflect.Field;
15 import java.lang.reflect.Modifier;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
25 import java.util.function.Predicate;
27 import static org.onap.config.ConfigurationUtils.getConfigurationRepositoryKey;
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;
210 if (tenant == null && namespace != null) {
211 tenantNamespaceArrayy = namespace.split(Constants.TENANT_NAMESPACE_SAPERATOR);
212 if (tenantNamespaceArrayy.length > 1) {
213 tenant = tenantNamespaceArrayy[0];
214 namespace = tenantNamespaceArrayy[1];
218 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
219 : Constants.DEFAULT_TENANT;
221 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
222 : Constants.DEFAULT_NAMESPACE;
223 T returnValue = null;
224 returnValue = (T) getInternal(tenant, namespace, key,
225 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
226 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
228 if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
229 && !Constants.DEFAULT_TENANT.equals(tenant)) {
230 returnValue = (T) getInternal(Constants.DEFAULT_TENANT, namespace, key,
231 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
232 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
235 if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
236 && !Constants.DEFAULT_NAMESPACE.equals(namespace)) {
237 returnValue = (T) getInternal(tenant, Constants.DEFAULT_NAMESPACE, key,
238 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
239 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
242 if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
243 && !Constants.DEFAULT_NAMESPACE.equals(namespace)
244 && !Constants.DEFAULT_TENANT.equals(tenant)) {
245 returnValue = (T) getInternal(Constants.DEFAULT_TENANT, Constants.DEFAULT_NAMESPACE, key,
246 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
247 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
250 if (returnValue == null && clazz.isPrimitive()) {
251 return (T) ConfigurationUtils.getDefaultFor(clazz);
261 * @param <T> the type parameter
262 * @param tenant the tenant
263 * @param namespace the namespace
265 * @param clazz the clazz
266 * @param hints the hints
267 * @return the internal
269 protected <T> T getInternal(String tenant, String namespace, String key, Class<T> clazz,
271 int processingHints = Hint.DEFAULT.value();
273 for (Hint hint : hints) {
274 processingHints = processingHints | hint.value();
278 if (tenant == null || tenant.trim().length() == 0) {
279 tenant = this.tenant.get();
281 tenant = tenant.toUpperCase();
283 if (namespace == null || namespace.trim().length() == 0) {
284 namespace = Constants.DEFAULT_NAMESPACE;
286 namespace = namespace.toUpperCase();
288 if (key == null || key.trim().length() == 0) {
289 if (!clazz.isAnnotationPresent(Config.class)) {
290 throw new IllegalArgumentException("Key can't be null.");
294 throw new IllegalArgumentException("clazz is null.");
296 if (clazz.isPrimitive()) {
297 clazz = getWrapperClass(clazz);
300 if (ConfigurationUtils.isWrapperClass(clazz) || clazz.isPrimitive()) {
303 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
304 key, processingHints);
306 if (ConfigurationUtils.isCollection(obj.toString())) {
307 obj = ConfigurationUtils.getCollectionString(obj.toString());
309 String value = obj.toString().split(",")[0];
310 value = ConfigurationUtils.processVariablesIfPresent(tenant, namespace, value);
311 return (T) getValue(value, clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
316 } else if (clazz.isArray()
317 && (clazz.getComponentType().isPrimitive() || ConfigurationUtils.isWrapperClass(clazz.getComponentType()))) {
320 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
321 key, processingHints);
323 Class componentClass = clazz.getComponentType();
324 if (clazz.getComponentType().isPrimitive()) {
325 componentClass = getWrapperClass(clazz.getComponentType());
327 String collString = ConfigurationUtils.getCollectionString(obj.toString());
328 ArrayList<String> tempCollection = new ArrayList<>();
329 for (String itemValue : collString.split(",")) {
331 .add(ConfigurationUtils.processVariablesIfPresent(tenant, namespace, itemValue));
333 Collection<T> collection = convert(
334 ConfigurationUtils.getCollectionString(Arrays.toString(tempCollection.toArray())),
335 componentClass, processingHints);
336 if (clazz.getComponentType().isPrimitive()) {
337 return (T) ConfigurationUtils.getPrimitiveArray(collection, clazz.getComponentType());
339 return (T) collection
340 .toArray(getZeroLengthArrayFor(getWrapperClass(clazz.getComponentType())));
345 } else if (clazz.isAnnotationPresent(Config.class)) {
346 return read(tenant, namespace, clazz,
347 (key == null || key.trim().length() == 0) ? "" : (key + "."), hints);
349 throw new IllegalArgumentException(
350 "Only pimitive classes, wrapper classes, corresponding array classes and any "
351 + "class decorated with @org.openecomp.config.api.Config are allowed as argument.");
353 } catch (Exception exception) {
354 exception.printStackTrace();
360 private <T> T read(String tenant, String namespace, Class<T> clazz, String keyPrefix,
361 Hint... hints) throws Exception {
363 clazz.getAnnotation(Config.class);
364 if (confAnnot != null && confAnnot.key().length()>0 && !keyPrefix.endsWith(".")) {
365 keyPrefix += (confAnnot.key() + ".");
367 Constructor<T> constructor = clazz.getDeclaredConstructor();
368 constructor.setAccessible(true);
369 T objToReturn = constructor.newInstance();
370 for (Field field : clazz.getDeclaredFields()) {
371 field.setAccessible(true);
372 Config fieldConfAnnot =
373 field.getAnnotation(Config.class);
374 if (fieldConfAnnot != null) {
375 if (field.getType().isPrimitive() || ConfigurationUtils.isWrapperClass(field.getType())
376 || (field.getType().isArray() && (field.getType().getComponentType().isPrimitive()
377 || ConfigurationUtils.isWrapperClass(field.getType().getComponentType())))
378 || field.getType().getAnnotation(Config.class) != null) {
379 field.set(objToReturn,
380 get(tenant, namespace, keyPrefix + fieldConfAnnot.key(), field.getType(), hints));
381 } else if (Collection.class.isAssignableFrom(field.getType())) {
382 Object obj = get(tenant, namespace, keyPrefix + fieldConfAnnot.key(),
383 ConfigurationUtils.getArrayClass(ConfigurationUtils.getCollectionGenericType(field)),
386 List list = Arrays.asList((Object[]) obj);
387 Class clazzToInstantiate = null;
388 if (field.getType().isInterface()) {
390 ConfigurationUtils.getConcreteCollection(field.getType()).getClass();
391 } else if (Modifier.isAbstract(field.getType().getModifiers())) {
393 ConfigurationUtils.getCompatibleCollectionForAbstractDef(field.getType())
396 clazzToInstantiate = field.getType();
398 Constructor construct =
399 getConstructorWithArguments(clazzToInstantiate, Collection.class);
400 if (construct != null) {
401 construct.setAccessible(true);
402 field.set(objToReturn, construct.newInstance(list));
403 } else if ((construct =
404 getConstructorWithArguments(clazzToInstantiate, Integer.class, Boolean.class,
405 Collection.class)) != null) {
406 construct.setAccessible(true);
407 field.set(objToReturn, construct.newInstance(list.size(), true, list));
410 }else if (Map.class.isAssignableFrom(field.getType())){
411 field.set(objToReturn, generateMap(tenant, namespace, keyPrefix+fieldConfAnnot.key()));
418 private Constructor getConstructorWithArguments(Class clazz, Class... classes) {
420 return clazz.getDeclaredConstructor(classes);
421 } catch (Exception exception) {
426 private Class getWrapperClass(Class clazz) {
427 if (byte.class == clazz) {
429 } else if (short.class == clazz) {
431 } else if (int.class == clazz) {
432 return Integer.class;
433 } else if (long.class == clazz) {
435 } else if (float.class == clazz) {
437 } else if (double.class == clazz) {
439 } else if (char.class == clazz) {
440 return Character.class;
441 } else if (boolean.class == clazz) {
442 return Boolean.class;
447 private <T> T getValue(Object obj, Class<T> clazz, int processingHint) {
448 if (obj == null || obj.toString().trim().length() == 0) {
451 obj = obj.toString().trim();
453 if (String.class.equals(clazz)) {
454 if (obj.toString().startsWith("@") && ConfigurationUtils.isExternalLookup(processingHint)) {
455 String contents = ConfigurationUtils
456 .getFileContents(NonConfigResource.locate(obj.toString().substring(1).trim()));
457 if (contents == null) {
458 contents = ConfigurationUtils.getFileContents(obj.toString().substring(1).trim());
460 if (contents != null) {
464 return (T) obj.toString();
465 } else if (Number.class.isAssignableFrom(clazz)) {
466 Double doubleValue = Double.valueOf(obj.toString());
467 switch (clazz.getName()) {
468 case "java.lang.Byte":
469 Byte byteVal = doubleValue.byteValue();
471 case "java.lang.Short":
472 Short shortVal = doubleValue.shortValue();
474 case "java.lang.Integer":
475 Integer intVal = doubleValue.intValue();
477 case "java.lang.Long":
478 Long longVal = doubleValue.longValue();
480 case "java.lang.Float":
481 Float floatVal = doubleValue.floatValue();
483 case "java.lang.Double":
484 Double doubleVal = doubleValue.doubleValue();
485 return (T) doubleVal;
488 } else if (Boolean.class.equals(clazz)) {
489 return (T) Boolean.valueOf(obj.toString());
490 } else if (Character.class.equals(clazz)) {
491 return (T) Character.valueOf(obj.toString().charAt(0));
496 private <T> T[] getZeroLengthArrayFor(Class<T> clazz) {
498 if (clazz == int.class) {
500 } else if (clazz == byte.class) {
502 } else if (clazz == short.class) {
504 } else if (clazz == long.class) {
506 } else if (clazz == float.class) {
508 } else if (clazz == double.class) {
509 obj = new double[]{};
510 } else if (clazz == boolean.class) {
511 obj = new boolean[]{};
512 } else if (clazz == char.class) {
514 } else if (clazz == Byte.class) {
516 } else if (clazz == Short.class) {
518 } else if (clazz == Integer.class) {
519 obj = new Integer[]{};
520 } else if (clazz == Long.class) {
522 } else if (clazz == Float.class) {
524 } else if (clazz == Double.class) {
525 obj = new Double[]{};
526 } else if (clazz == Boolean.class) {
527 obj = new Boolean[]{};
528 } else if (clazz == Character.class) {
529 obj = new Character[]{};
530 } else if (clazz == String.class) {
531 obj = new String[]{};
536 private <T> Collection<T> convert(String commaSaperatedValues, Class<T> clazz,
537 int processingHints) {
538 ArrayList<T> collection = new ArrayList<>();
539 for (String value : commaSaperatedValues.split(",")) {
541 T type1 = getValue(value, clazz, processingHints);
543 collection.add(type1);
545 } catch (RuntimeException re) {
555 public void shutdown() {
556 if (changeNotifier != null) {
558 changeNotifier.shutdown();
559 ConfigurationDataSource.lookup().close();
560 } catch (Exception exception) {
561 exception.printStackTrace();
567 public void removeConfigurationChangeListener(String tenant, String namespace, String key,
568 ConfigurationChangeListener myself) {
569 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
570 : Constants.DEFAULT_TENANT;
572 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
573 : Constants.DEFAULT_NAMESPACE;
574 if (key == null || key.trim().length() == 0) {
575 throw new IllegalArgumentException("Key can't be null.");
578 changeNotifier.stopNotificationTowards(tenant, namespace, key, myself);
579 } catch (Exception exception) {
580 exception.printStackTrace();
585 public <T> Map<String, T> populateMap(String tenantId, String namespace, String key, Class<T> clazz){
586 if (tenantId==null || tenantId.trim().length()==0){
587 tenantId = this.tenant.get();
589 tenantId = tenantId.toUpperCase();
591 if (namespace==null || namespace.trim().length()==0){
592 namespace = Constants.DEFAULT_NAMESPACE;
594 namespace = namespace.toUpperCase();
596 Map<String, T> map = new HashMap<>();
597 Iterator<String> keys ;
599 if (ConfigurationRepository.lookup().isDBAccessible()){
600 keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor(
601 Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+ Constants.KEY_ELEMENTS_DELEMETER+namespace}).iterator();
603 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
605 while(keys.hasNext()){
606 String k = keys.next();
607 if (k.startsWith(key+".")){
608 k = k.substring(key.length()+1);
609 String subkey = k.substring(0, k.indexOf("."));
610 if (!map.containsKey(subkey)){
611 map.put(subkey, get(tenantId, namespace, key+"."+subkey, clazz));
615 }catch (Exception e){
622 public Map generateMap(String tenantId, String namespace, String key){
623 if (tenantId==null || tenantId.trim().length()==0){
624 tenantId = this.tenant.get();
626 tenantId = tenantId.toUpperCase();
628 if (namespace==null || namespace.trim().length()==0){
629 namespace = Constants.DEFAULT_NAMESPACE;
631 namespace = namespace.toUpperCase();
633 Map map, parentMap = new HashMap<>();
634 Iterator<String> keys ;
636 if (ConfigurationRepository.lookup().isDBAccessible()){
637 keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor(
638 Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+ Constants.KEY_ELEMENTS_DELEMETER+namespace}).iterator();
640 if (key==null || key.trim().length()==0){
641 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys();
643 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
646 while(keys.hasNext()){
648 String k = keys.next();
650 if (key!=null && key.trim().length()!=0 && !k.startsWith(key+".")){
653 String value = getAsString(tenantId, namespace, k);
654 if (key!=null && key.trim().length()!=0 && k.startsWith(key+".")){
655 k = k.substring(key.trim().length()+1);
658 while(k.contains(".")){
659 if (k.contains(".")){
660 String subkey = k.substring(0, k.indexOf("."));
661 k = k.substring(k.indexOf(".")+1);
662 if (!map.containsKey(subkey)){
663 map.put(subkey, map=new HashMap<>());
665 map = (Map)map.get(subkey);
671 }catch (Exception e){