1 package org.openecomp.config.impl;
3 import static org.openecomp.config.ConfigurationUtils.getConfigurationRepositoryKey;
4 import static org.openecomp.config.ConfigurationUtils.getProperty;
5 import static org.openecomp.config.ConfigurationUtils.isExternalLookup;
6 import static org.openecomp.config.ConfigurationUtils.isWrapperClass;
7 import static org.openecomp.config.ConfigurationUtils.isZeroLengthArray;
9 import static org.openecomp.config.Constants.DB_NAMESPACE;
10 import static org.openecomp.config.Constants.DEFAULT_NAMESPACE;
11 import static org.openecomp.config.Constants.DEFAULT_TENANT;
12 import static org.openecomp.config.Constants.KEY_ELEMENTS_DELEMETER;
14 import org.apache.commons.configuration2.Configuration;
15 import org.apache.commons.configuration2.DatabaseConfiguration;
16 import org.openecomp.config.ConfigurationUtils;
17 import org.openecomp.config.Constants;
18 import org.openecomp.config.NonConfigResource;
19 import org.openecomp.config.api.Config;
20 import org.openecomp.config.api.ConfigurationChangeListener;
21 import org.openecomp.config.api.Hint;
24 import java.lang.reflect.Constructor;
25 import java.lang.reflect.Field;
26 import java.lang.reflect.Modifier;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
36 import java.util.function.Predicate;
39 * The type Configuration.
41 public class ConfigurationImpl implements org.openecomp.config.api.Configuration {
43 private static ThreadLocal<String> tenant = new ThreadLocal<String>() {
44 protected String initialValue() {
45 return Constants.DEFAULT_TENANT;
50 private static boolean instantiated = false;
52 * The Change notifier.
54 ConfigurationChangeNotifier changeNotifier;
57 * Instantiates a new Configuration.
59 * @throws Exception the exception
61 public ConfigurationImpl() throws Exception {
62 if (instantiated || !CliConfigurationImpl.class.isAssignableFrom(this.getClass())) {
63 throw new RuntimeException("Illegal access to configuration.");
65 Map<String, AggregateConfiguration> moduleConfigStore = new HashMap<>();
66 List<URL> classpathResources = ConfigurationUtils.getAllClassPathResources();
67 Predicate<URL> predicate = ConfigurationUtils::isConfig;
68 for (URL url : classpathResources) {
69 if (predicate.test(url)) {
70 String moduleName = getConfigurationRepositoryKey(url);
71 AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
72 if (moduleConfig == null) {
73 moduleConfig = new AggregateConfiguration();
74 moduleConfigStore.put(moduleName, moduleConfig);
76 moduleConfig.addConfig(url);
78 NonConfigResource.add(url);
81 String configLocation = System.getProperty("config.location");
82 if (configLocation != null && configLocation.trim().length() > 0) {
83 File root = new File(configLocation);
84 Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
85 Predicate<File> filePredicate = ConfigurationUtils::isConfig;
86 for (File file : filesystemResources) {
87 if (filePredicate.test(file)) {
88 String moduleName = getConfigurationRepositoryKey(file);
89 AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
90 if (moduleConfig == null) {
91 moduleConfig = new AggregateConfiguration();
92 moduleConfigStore.put(moduleName, moduleConfig);
94 moduleConfig.addConfig(file);
96 NonConfigResource.add(file);
100 String tenantConfigLocation = System.getProperty("tenant.config.location");
101 if (tenantConfigLocation != null && tenantConfigLocation.trim().length() > 0) {
102 File root = new File(tenantConfigLocation);
103 Collection<File> tenantsRoot = ConfigurationUtils.getAllFiles(root, false, true);
104 Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
105 Predicate<File> filePredicate = ConfigurationUtils::isConfig;
106 for (File file : filesystemResources) {
107 if (filePredicate.test(file)) {
108 String moduleName = ConfigurationUtils.getNamespace(file);
109 for (File tenanatFileRoot : tenantsRoot) {
110 if (file.getAbsolutePath().startsWith(tenanatFileRoot.getAbsolutePath())) {
111 moduleName = getConfigurationRepositoryKey(
112 (tenanatFileRoot.getName().toUpperCase() + Constants.TENANT_NAMESPACE_SAPERATOR
113 + moduleName).split(Constants.TENANT_NAMESPACE_SAPERATOR));
116 AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
117 if (moduleConfig == null) {
118 moduleConfig = new AggregateConfiguration();
119 moduleConfigStore.put(moduleName, moduleConfig);
121 moduleConfig.addConfig(file);
125 populateFinalConfigurationIncrementally(moduleConfigStore);
126 ConfigurationRepository.lookup().initTenantsAndNamespaces();
127 String nodeConfigLocation = System.getProperty("node.config.location");
128 if (nodeConfigLocation != null && nodeConfigLocation.trim().length() > 0) {
129 File root = new File(nodeConfigLocation);
130 Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
131 Predicate<File> filePredicate = ConfigurationUtils::isConfig;
132 for (File file : filesystemResources) {
133 if (filePredicate.test(file)) {
134 ConfigurationRepository.lookup().populateOverrideConfigurtaion(
135 getConfigurationRepositoryKey(ConfigurationUtils.getNamespace(file)
136 .split(Constants.TENANT_NAMESPACE_SAPERATOR)), file);
141 changeNotifier = new ConfigurationChangeNotifier(moduleConfigStore);
145 public void addConfigurationChangeListener(String tenant, String namespace, String key,
146 ConfigurationChangeListener myself) {
147 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
148 : Constants.DEFAULT_TENANT;
150 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
151 : Constants.DEFAULT_NAMESPACE;
152 if (key == null || key.trim().length() == 0) {
153 throw new IllegalArgumentException("Key can't be null.");
155 if (myself == null) {
156 throw new IllegalArgumentException("ConfigurationChangeListener instance is null.");
159 changeNotifier.notifyChangesTowards(tenant, namespace, key, myself);
160 } catch (Exception exception) {
161 exception.printStackTrace();
165 private void populateFinalConfigurationIncrementally(Map<String, AggregateConfiguration> configs)
167 boolean isDbAccessible = false;
169 Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE)
171 ConfigurationRepository.lookup().populateConfigurtaion(
172 Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE,
174 Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE)
175 .getFinalConfiguration());
176 isDbAccessible = ConfigurationUtils.executeDdlSql(ConfigurationRepository.lookup()
177 .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
178 .getString("createtablecql"));
179 if (isDbAccessible) {
180 ConfigurationUtils.executeDdlSql(ConfigurationRepository.lookup()
181 .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE)
182 .getString("createmonitoringtablecql"));
186 Set<String> modules = configs.keySet();
187 for (String module : modules) {
188 if (isDbAccessible) {
189 DatabaseConfiguration config =
190 ConfigurationUtils.getDbConfigurationBuilder(module).getConfiguration();
191 Configuration currentConfig = configs.get(module).getFinalConfiguration();
192 Iterator<String> keys = currentConfig.getKeys();
193 while (keys.hasNext()) {
194 String currentKey = keys.next();
195 if (!(Constants.MODE_KEY.equals(currentKey)
196 || Constants.NAMESPACE_KEY.equals(currentKey)
197 || Constants.LOAD_ORDER_KEY.equals(currentKey))) {
198 if (!config.containsKey(currentKey)) {
199 Object propValue = currentConfig.getProperty(currentKey);
200 if (propValue instanceof Collection) {
201 config.addProperty(currentKey, propValue.toString());
203 config.addProperty(currentKey, propValue);
209 ConfigurationRepository.lookup()
210 .populateConfigurtaion(module, configs.get(module).getFinalConfiguration());
216 public <T> T get(String tenant, String namespace, String key, Class<T> clazz, Hint... hints) {
218 String[] tenantNamespaceArrayy = null;
219 if (tenant == null && namespace != null
220 && (tenantNamespaceArrayy = namespace.split(Constants.TENANT_NAMESPACE_SAPERATOR)).length
222 tenant = tenantNamespaceArrayy[0];
223 namespace = tenantNamespaceArrayy[1];
226 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
227 : Constants.DEFAULT_TENANT;
229 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
230 : Constants.DEFAULT_NAMESPACE;
231 T returnValue = null;
232 returnValue = (T) getInternal(tenant, namespace, key,
233 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
234 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
236 if ((returnValue == null || isZeroLengthArray(clazz, returnValue))
237 && !Constants.DEFAULT_TENANT.equals(tenant)) {
238 returnValue = (T) getInternal(Constants.DEFAULT_TENANT, namespace, key,
239 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
240 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
243 if ((returnValue == null || isZeroLengthArray(clazz, returnValue))
244 && !Constants.DEFAULT_NAMESPACE.equals(namespace)) {
245 returnValue = (T) getInternal(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 ||isZeroLengthArray(clazz, returnValue))
251 && !Constants.DEFAULT_NAMESPACE.equals(namespace)
252 && !Constants.DEFAULT_TENANT.equals(tenant)) {
253 returnValue = (T) getInternal(Constants.DEFAULT_TENANT, Constants.DEFAULT_NAMESPACE, key,
254 clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
255 hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
258 if (returnValue == null && clazz.isPrimitive()) {
259 return (T) ConfigurationUtils.getDefaultFor(clazz);
269 * @param <T> the type parameter
270 * @param tenant the tenant
271 * @param namespace the namespace
273 * @param clazz the clazz
274 * @param hints the hints
275 * @return the internal
277 protected <T> T getInternal(String tenant, String namespace, String key, Class<T> clazz,
279 int processingHints = Hint.DEFAULT.value();
281 for (Hint hint : hints) {
282 processingHints = processingHints | hint.value();
286 if (tenant == null || tenant.trim().length() == 0) {
287 tenant = this.tenant.get();
289 tenant = tenant.toUpperCase();
291 if (namespace == null || namespace.trim().length() == 0) {
292 namespace = Constants.DEFAULT_NAMESPACE;
294 namespace = namespace.toUpperCase();
296 if (key == null || key.trim().length() == 0) {
297 if (!clazz.isAnnotationPresent(Config.class)) {
298 throw new IllegalArgumentException("Key can't be null.");
302 throw new IllegalArgumentException("clazz is null.");
304 if (clazz.isPrimitive()) {
305 clazz = getWrapperClass(clazz);
308 if (isWrapperClass(clazz) || clazz.isPrimitive()) {
310 getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
311 key, processingHints);
313 if (ConfigurationUtils.isCollection(obj.toString())) {
314 obj = ConfigurationUtils.getCollectionString(obj.toString());
316 String value = obj.toString().split(",")[0];
317 value = ConfigurationUtils.processVariablesIfPresent(tenant, namespace, value);
318 return (T) getValue(value, clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
323 } else if (clazz.isArray()
324 && (clazz.getComponentType().isPrimitive() || isWrapperClass(clazz.getComponentType()))) {
326 getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
327 key, processingHints);
329 Class componentClass = clazz.getComponentType();
330 if (clazz.getComponentType().isPrimitive()) {
331 componentClass = getWrapperClass(clazz.getComponentType());
333 String collString = ConfigurationUtils.getCollectionString(obj.toString());
334 ArrayList<String> tempCollection = new ArrayList<>();
335 for (String itemValue : collString.split(",")) {
337 .add(ConfigurationUtils.processVariablesIfPresent(tenant, namespace, itemValue));
339 Collection<T> collection = convert(
340 ConfigurationUtils.getCollectionString(Arrays.toString(tempCollection.toArray())),
341 componentClass, processingHints);
342 if (clazz.getComponentType().isPrimitive()) {
343 return (T) ConfigurationUtils.getPrimitiveArray(collection, clazz.getComponentType());
345 return (T) collection
346 .toArray(getZeroLengthArrayFor(getWrapperClass(clazz.getComponentType())));
351 } else if (clazz.isAnnotationPresent(Config.class)) {
352 return read(tenant, namespace, clazz,
353 (key == null || key.trim().length() == 0) ? "" : (key + "."), hints);
355 throw new IllegalArgumentException(
356 "Only pimitive classes, wrapper classes, corresponding array classes and any "
357 + "class decorated with @org.openecomp.config.api.Config are allowed as argument.");
359 } catch (Exception exception) {
360 exception.printStackTrace();
366 private <T> T read(String tenant, String namespace, Class<T> clazz, String keyPrefix,
367 Hint... hints) throws Exception {
368 org.openecomp.config.api.Config confAnnot =
369 clazz.getAnnotation(org.openecomp.config.api.Config.class);
370 if (confAnnot != null && confAnnot.key().length()>0 && !keyPrefix.endsWith(".")) {
371 keyPrefix += (confAnnot.key() + ".");
373 Constructor<T> constructor = clazz.getDeclaredConstructor();
374 constructor.setAccessible(true);
375 T objToReturn = constructor.newInstance();
376 for (Field field : clazz.getDeclaredFields()) {
377 field.setAccessible(true);
378 org.openecomp.config.api.Config fieldConfAnnot =
379 field.getAnnotation(org.openecomp.config.api.Config.class);
380 if (fieldConfAnnot != null) {
381 if (field.getType().isPrimitive() || isWrapperClass(field.getType())
382 || (field.getType().isArray() && (field.getType().getComponentType().isPrimitive()
383 || isWrapperClass(field.getType().getComponentType())))
384 || field.getType().getAnnotation(org.openecomp.config.api.Config.class) != null) {
385 field.set(objToReturn,
386 get(tenant, namespace, keyPrefix + fieldConfAnnot.key(), field.getType(), hints));
387 } else if (Collection.class.isAssignableFrom(field.getType())) {
388 Object obj = get(tenant, namespace, keyPrefix + fieldConfAnnot.key(),
389 ConfigurationUtils.getArrayClass(ConfigurationUtils.getCollectionGenericType(field)),
392 List list = Arrays.asList((Object[]) obj);
393 Class clazzToInstantiate = null;
394 if (field.getType().isInterface()) {
396 ConfigurationUtils.getConcreteCollection(field.getType()).getClass();
397 } else if (Modifier.isAbstract(field.getType().getModifiers())) {
399 ConfigurationUtils.getCompatibleCollectionForAbstractDef(field.getType())
402 clazzToInstantiate = field.getType();
404 Constructor construct =
405 getConstructorWithArguments(clazzToInstantiate, Collection.class);
406 if (construct != null) {
407 construct.setAccessible(true);
408 field.set(objToReturn, construct.newInstance(list));
409 } else if ((construct =
410 getConstructorWithArguments(clazzToInstantiate, Integer.class, Boolean.class,
411 Collection.class)) != null) {
412 construct.setAccessible(true);
413 field.set(objToReturn, construct.newInstance(list.size(), true, list));
416 }else if (Map.class.isAssignableFrom(field.getType())){
417 field.set(objToReturn, generateMap(tenant, namespace, keyPrefix+fieldConfAnnot.key()));
424 private Constructor getConstructorWithArguments(Class clazz, Class... classes) {
426 return clazz.getDeclaredConstructor(classes);
427 } catch (Exception exception) {
432 private Class getWrapperClass(Class clazz) {
433 if (byte.class == clazz) {
435 } else if (short.class == clazz) {
437 } else if (int.class == clazz) {
438 return Integer.class;
439 } else if (long.class == clazz) {
441 } else if (float.class == clazz) {
443 } else if (double.class == clazz) {
445 } else if (char.class == clazz) {
446 return Character.class;
447 } else if (boolean.class == clazz) {
448 return Boolean.class;
453 private <T> T getValue(Object obj, Class<T> clazz, int processingHint) {
454 if (obj == null || obj.toString().trim().length() == 0) {
457 obj = obj.toString().trim();
459 if (String.class.equals(clazz)) {
460 if (obj.toString().startsWith("@") && isExternalLookup(processingHint)) {
461 String contents = ConfigurationUtils
462 .getFileContents(NonConfigResource.locate(obj.toString().substring(1).trim()));
463 if (contents == null) {
464 contents = ConfigurationUtils.getFileContents(obj.toString().substring(1).trim());
466 if (contents != null) {
470 return (T) obj.toString();
471 } else if (Number.class.isAssignableFrom(clazz)) {
472 Double doubleValue = Double.valueOf(obj.toString());
473 switch (clazz.getName()) {
474 case "java.lang.Byte":
475 Byte byteVal = doubleValue.byteValue();
477 case "java.lang.Short":
478 Short shortVal = doubleValue.shortValue();
480 case "java.lang.Integer":
481 Integer intVal = doubleValue.intValue();
483 case "java.lang.Long":
484 Long longVal = doubleValue.longValue();
486 case "java.lang.Float":
487 Float floatVal = doubleValue.floatValue();
489 case "java.lang.Double":
490 Double doubleVal = doubleValue.doubleValue();
491 return (T) doubleVal;
494 } else if (Boolean.class.equals(clazz)) {
495 return (T) Boolean.valueOf(obj.toString());
496 } else if (Character.class.equals(clazz)) {
497 return (T) Character.valueOf(obj.toString().charAt(0));
502 private <T> T[] getZeroLengthArrayFor(Class<T> clazz) {
504 if (clazz == int.class) {
506 } else if (clazz == byte.class) {
508 } else if (clazz == short.class) {
510 } else if (clazz == long.class) {
512 } else if (clazz == float.class) {
514 } else if (clazz == double.class) {
515 obj = new double[]{};
516 } else if (clazz == boolean.class) {
517 obj = new boolean[]{};
518 } else if (clazz == char.class) {
520 } else if (clazz == Byte.class) {
522 } else if (clazz == Short.class) {
524 } else if (clazz == Integer.class) {
525 obj = new Integer[]{};
526 } else if (clazz == Long.class) {
528 } else if (clazz == Float.class) {
530 } else if (clazz == Double.class) {
531 obj = new Double[]{};
532 } else if (clazz == Boolean.class) {
533 obj = new Boolean[]{};
534 } else if (clazz == Character.class) {
535 obj = new Character[]{};
536 } else if (clazz == String.class) {
537 obj = new String[]{};
542 private <T> Collection<T> convert(String commaSaperatedValues, Class<T> clazz,
543 int processingHints) {
544 ArrayList<T> collection = new ArrayList<>();
545 for (String value : commaSaperatedValues.split(",")) {
547 T type1 = getValue(value, clazz, processingHints);
549 collection.add(type1);
551 } catch (RuntimeException re) {
561 public void shutdown() {
562 if (changeNotifier != null) {
564 changeNotifier.shutdown();
565 ConfigurationDataSource.lookup().close();
566 } catch (Exception exception) {
567 exception.printStackTrace();
573 public void removeConfigurationChangeListener(String tenant, String namespace, String key,
574 ConfigurationChangeListener myself) {
575 tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
576 : Constants.DEFAULT_TENANT;
578 ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
579 : Constants.DEFAULT_NAMESPACE;
580 if (key == null || key.trim().length() == 0) {
581 throw new IllegalArgumentException("Key can't be null.");
584 changeNotifier.stopNotificationTowards(tenant, namespace, key, myself);
585 } catch (Exception exception) {
586 exception.printStackTrace();
591 public <T> Map<String, T> populateMap(String tenantId, String namespace, String key, Class<T> clazz){
592 if (tenantId==null || tenantId.trim().length()==0){
593 tenantId = this.tenant.get();
595 tenantId = tenantId.toUpperCase();
597 if (namespace==null || namespace.trim().length()==0){
598 namespace = DEFAULT_NAMESPACE;
600 namespace = namespace.toUpperCase();
602 Map<String, T> map = new HashMap<>();
603 Iterator<String> keys ;
605 if (ConfigurationRepository.lookup().isDBAccessible()){
606 keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+KEY_ELEMENTS_DELEMETER+namespace}).iterator();
608 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
610 while(keys.hasNext()){
611 String k = keys.next();
612 if (k.startsWith(key+".")){
613 k = k.substring(key.length()+1);
614 String subkey = k.substring(0, k.indexOf("."));
615 if (!map.containsKey(subkey)){
616 map.put(subkey, get(tenantId, namespace, key+"."+subkey, clazz));
620 }catch (Exception e){
627 public Map generateMap(String tenantId, String namespace, String key){
628 if (tenantId==null || tenantId.trim().length()==0){
629 tenantId = this.tenant.get();
631 tenantId = tenantId.toUpperCase();
633 if (namespace==null || namespace.trim().length()==0){
634 namespace = DEFAULT_NAMESPACE;
636 namespace = namespace.toUpperCase();
638 Map map, parentMap = new HashMap<>();
639 Iterator<String> keys ;
641 if (ConfigurationRepository.lookup().isDBAccessible()){
642 keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+KEY_ELEMENTS_DELEMETER+namespace}).iterator();
644 if (key==null || key.trim().length()==0){
645 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys();
647 keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
650 while(keys.hasNext()){
652 String k = keys.next();
654 if (key!=null && key.trim().length()!=0 && !k.startsWith(key+".")){
657 String value = getAsString(tenantId, namespace, k);
658 if (key!=null && key.trim().length()!=0 && k.startsWith(key+".")){
659 k = k.substring(key.trim().length()+1);
662 while(k.contains(".")){
663 if (k.contains(".")){
664 String subkey = k.substring(0, k.indexOf("."));
665 k = k.substring(k.indexOf(".")+1);
666 if (!map.containsKey(subkey)){
667 map.put(subkey, map=new HashMap<>());
669 map = (Map)map.get(subkey);
675 }catch (Exception e){