Removed code that stored configuration in DB
[sdc.git] / common / onap-common-configuration-management / onap-configuration-management-core / src / main / java / org / onap / config / impl / ConfigurationImpl.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.config.impl;
18
19 import java.io.File;
20 import java.lang.reflect.Constructor;
21 import java.lang.reflect.Field;
22 import java.lang.reflect.Modifier;
23 import java.net.URL;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.function.Predicate;
33 import org.onap.config.ConfigurationUtils;
34 import org.onap.config.Constants;
35 import org.onap.config.NonConfigResource;
36 import org.onap.config.api.Config;
37 import org.onap.config.api.ConfigurationChangeListener;
38 import org.onap.config.api.Hint;
39
40 /**
41  * The type Configuration.
42  */
43 public class ConfigurationImpl implements org.onap.config.api.Configuration {
44
45   private static final String KEY_CANNOT_BE_NULL = "Key can't be null.";
46   private static ThreadLocal<String> tenant = new ThreadLocal<String>() {
47
48     @Override
49     protected String initialValue() {
50       return Constants.DEFAULT_TENANT;
51     }
52
53     ;
54   };
55   private static boolean instantiated = false;
56   /**
57    * The Change notifier.
58    */
59   ConfigurationChangeNotifier changeNotifier;
60
61   /**
62    * Instantiates a new Configuration.
63    *
64    * @throws Exception the exception
65    */
66   public ConfigurationImpl() throws Exception {
67     if (instantiated || !CliConfigurationImpl.class.isAssignableFrom(this.getClass())) {
68       throw new RuntimeException("Illegal access to configuration.");
69     }
70     Map<String, AggregateConfiguration> moduleConfigStore = new HashMap<>();
71     List<URL> classpathResources = ConfigurationUtils.getAllClassPathResources();
72     Predicate<URL> predicate = ConfigurationUtils::isConfig;
73     for (URL url : classpathResources) {
74       if (predicate.test(url)) {
75         String moduleName = ConfigurationUtils.getConfigurationRepositoryKey(url);
76         AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
77         if (moduleConfig == null) {
78           moduleConfig = new AggregateConfiguration();
79           moduleConfigStore.put(moduleName, moduleConfig);
80         }
81         moduleConfig.addConfig(url);
82       } else {
83         NonConfigResource.add(url);
84       }
85     }
86     String configLocation = System.getProperty("config.location");
87     if (configLocation != null && configLocation.trim().length() > 0) {
88       File root = new File(configLocation);
89       Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
90       Predicate<File> filePredicate = ConfigurationUtils::isConfig;
91       for (File file : filesystemResources) {
92         if (filePredicate.test(file)) {
93           String moduleName = ConfigurationUtils.getConfigurationRepositoryKey(file);
94           AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
95           if (moduleConfig == null) {
96             moduleConfig = new AggregateConfiguration();
97             moduleConfigStore.put(moduleName, moduleConfig);
98           }
99           moduleConfig.addConfig(file);
100         } else {
101           NonConfigResource.add(file);
102         }
103       }
104     }
105     String tenantConfigLocation = System.getProperty("tenant.config.location");
106     if (tenantConfigLocation != null && tenantConfigLocation.trim().length() > 0) {
107       File root = new File(tenantConfigLocation);
108       Collection<File> tenantsRoot = ConfigurationUtils.getAllFiles(root, false, true);
109       Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
110       Predicate<File> filePredicate = ConfigurationUtils::isConfig;
111       for (File file : filesystemResources) {
112         if (filePredicate.test(file)) {
113           String moduleName = ConfigurationUtils.getNamespace(file);
114           for (File tenanatFileRoot : tenantsRoot) {
115             if (file.getAbsolutePath().startsWith(tenanatFileRoot.getAbsolutePath())) {
116               moduleName = ConfigurationUtils.getConfigurationRepositoryKey(
117                   (tenanatFileRoot.getName().toUpperCase() + Constants.TENANT_NAMESPACE_SAPERATOR
118                       + moduleName).split(Constants.TENANT_NAMESPACE_SAPERATOR));
119             }
120           }
121           AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName);
122           if (moduleConfig == null) {
123             moduleConfig = new AggregateConfiguration();
124             moduleConfigStore.put(moduleName, moduleConfig);
125           }
126           moduleConfig.addConfig(file);
127         }
128       }
129     }
130     populateFinalConfigurationIncrementally(moduleConfigStore);
131     ConfigurationRepository.lookup().initTenantsAndNamespaces();
132     String nodeConfigLocation = System.getProperty("node.config.location");
133     if (nodeConfigLocation != null && nodeConfigLocation.trim().length() > 0) {
134       File root = new File(nodeConfigLocation);
135       Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
136       Predicate<File> filePredicate = ConfigurationUtils::isConfig;
137       for (File file : filesystemResources) {
138         if (filePredicate.test(file)) {
139           ConfigurationRepository.lookup().populateOverrideConfigurtaion(
140               ConfigurationUtils.getConfigurationRepositoryKey(ConfigurationUtils.getNamespace(file)
141                   .split(Constants.TENANT_NAMESPACE_SAPERATOR)), file);
142         }
143       }
144     }
145     instantiated = true;
146     changeNotifier = new ConfigurationChangeNotifier(moduleConfigStore);
147   }
148
149   @Override
150   public void addConfigurationChangeListener(String tenant, String namespace, String key,
151                                              ConfigurationChangeListener myself) {
152     tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
153         : Constants.DEFAULT_TENANT;
154     namespace =
155         ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
156             : Constants.DEFAULT_NAMESPACE;
157     if (key == null || key.trim().length() == 0) {
158       throw new IllegalArgumentException(KEY_CANNOT_BE_NULL);
159     }
160     if (myself == null) {
161       throw new IllegalArgumentException("ConfigurationChangeListener instance is null.");
162     }
163     try {
164       changeNotifier.notifyChangesTowards(tenant, namespace, key, myself);
165     } catch (Exception exception) {
166       exception.printStackTrace();
167     }
168   }
169
170   private void populateFinalConfigurationIncrementally(Map<String, AggregateConfiguration> configs) {
171
172     if (configs.get(
173         Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE)
174         != null) {
175       ConfigurationRepository.lookup().populateConfigurtaion(
176           Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE,
177           configs.remove(
178               Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE)
179               .getFinalConfiguration());
180     }
181
182     Set<String> modules = configs.keySet();
183     for (String module : modules) {
184         ConfigurationRepository.lookup()
185             .populateConfigurtaion(module, configs.get(module).getFinalConfiguration());
186     }
187   }
188
189   @Override
190   public <T> T get(String tenant, String namespace, String key, Class<T> clazz, Hint... hints) {
191
192     String[] tenantNamespaceArrayy;
193     if (tenant == null && namespace != null) {
194       tenantNamespaceArrayy = namespace.split(Constants.TENANT_NAMESPACE_SAPERATOR);
195       if (tenantNamespaceArrayy.length > 1) {
196         tenant = tenantNamespaceArrayy[0];
197         namespace = tenantNamespaceArrayy[1];
198       }
199     }
200
201     tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
202         : Constants.DEFAULT_TENANT;
203     namespace =
204         ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
205             : Constants.DEFAULT_NAMESPACE;
206     T returnValue = null;
207     returnValue = (T) getInternal(tenant, namespace, key,
208         clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
209         hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
210             : hints);
211     if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
212         && !Constants.DEFAULT_TENANT.equals(tenant)) {
213       returnValue = (T) getInternal(Constants.DEFAULT_TENANT, namespace, key,
214           clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
215           hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
216               : hints);
217     }
218     if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
219         && !Constants.DEFAULT_NAMESPACE.equals(namespace)) {
220       returnValue = (T) getInternal(tenant, Constants.DEFAULT_NAMESPACE, key,
221           clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
222           hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
223               : hints);
224     }
225     if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue))
226         && !Constants.DEFAULT_NAMESPACE.equals(namespace)
227         && !Constants.DEFAULT_TENANT.equals(tenant)) {
228       returnValue = (T) getInternal(Constants.DEFAULT_TENANT, Constants.DEFAULT_NAMESPACE, key,
229           clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
230           hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC}
231               : hints);
232     }
233     if (returnValue == null && clazz.isPrimitive()) {
234       return (T) ConfigurationUtils.getDefaultFor(clazz);
235     } else {
236       return returnValue;
237     }
238   }
239
240
241   /**
242    * Gets internal.
243    *
244    * @param <T>       the type parameter
245    * @param tenant    the tenant
246    * @param namespace the namespace
247    * @param key       the key
248    * @param clazz     the clazz
249    * @param hints     the hints
250    * @return the internal
251    */
252   protected <T> T getInternal(String tenant, String namespace, String key, Class<T> clazz,
253                               Hint... hints) {
254     int processingHints = Hint.DEFAULT.value();
255     if (hints != null) {
256       for (Hint hint : hints) {
257         processingHints = processingHints | hint.value();
258       }
259     }
260
261     if (tenant == null || tenant.trim().length() == 0) {
262       tenant = ConfigurationImpl.tenant.get();
263     } else {
264       tenant = tenant.toUpperCase();
265     }
266     if (namespace == null || namespace.trim().length() == 0) {
267       namespace = Constants.DEFAULT_NAMESPACE;
268     } else {
269       namespace = namespace.toUpperCase();
270     }
271     if ((key == null || key.trim().length() == 0) && !clazz.isAnnotationPresent(Config.class)) {
272       throw new IllegalArgumentException(KEY_CANNOT_BE_NULL);
273     }
274     if (clazz == null) {
275       throw new IllegalArgumentException("clazz is null.");
276     }
277     if (clazz.isPrimitive()) {
278       clazz = getWrapperClass(clazz);
279     }
280     try {
281       if (ConfigurationUtils.isWrapperClass(clazz) || clazz.isPrimitive()) {
282         Object obj =
283             ConfigurationUtils
284                 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
285                 key, processingHints);
286         if (obj != null) {
287           if (ConfigurationUtils.isCollection(obj.toString())) {
288             obj = ConfigurationUtils.getCollectionString(obj.toString());
289           }
290           String value = obj.toString().split(",")[0];
291           value = ConfigurationUtils.processVariablesIfPresent(tenant, namespace, value);
292           return (T) getValue(value, clazz.isPrimitive() ? getWrapperClass(clazz) : clazz,
293               processingHints);
294         } else {
295           return null;
296         }
297       } else if (clazz.isArray()
298           && (clazz.getComponentType().isPrimitive() || ConfigurationUtils.isWrapperClass(clazz.getComponentType()))) {
299         Object obj =
300             ConfigurationUtils
301                 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace),
302                 key, processingHints);
303         if (obj != null) {
304           Class componentClass = clazz.getComponentType();
305           if (clazz.getComponentType().isPrimitive()) {
306             componentClass = getWrapperClass(clazz.getComponentType());
307           }
308           String collString = ConfigurationUtils.getCollectionString(obj.toString());
309           ArrayList<String> tempCollection = new ArrayList<>();
310           for (String itemValue : collString.split(",")) {
311             tempCollection
312                 .add(ConfigurationUtils.processVariablesIfPresent(tenant, namespace, itemValue));
313           }
314           Collection<T> collection = convert(
315               ConfigurationUtils.getCollectionString(Arrays.toString(tempCollection.toArray())),
316               componentClass, processingHints);
317           if (clazz.getComponentType().isPrimitive()) {
318             return (T) ConfigurationUtils.getPrimitiveArray(collection, clazz.getComponentType());
319           } else {
320             return (T) collection
321                 .toArray(getZeroLengthArrayFor(getWrapperClass(clazz.getComponentType())));
322           }
323         } else {
324           return null;
325         }
326       } else if (clazz.isAnnotationPresent(Config.class)) {
327         return read(tenant, namespace, clazz,
328             (key == null || key.trim().length() == 0) ? "" : (key + "."), hints);
329       } else {
330         throw new IllegalArgumentException(
331             "Only pimitive classes, wrapper classes, corresponding array classes and any "
332                 + "class decorated with @org.openecomp.config.api.Config are allowed as argument.");
333       }
334     } catch (Exception exception) {
335       exception.printStackTrace();
336     }
337     return null;
338   }
339
340
341   private <T> T read(String tenant, String namespace, Class<T> clazz, String keyPrefix,
342                      Hint... hints) throws Exception {
343     Config confAnnot =
344         clazz.getAnnotation(Config.class);
345     if (confAnnot != null && confAnnot.key().length()>0 && !keyPrefix.endsWith(".")) {
346       keyPrefix += (confAnnot.key() + ".");
347     }
348     Constructor<T> constructor = clazz.getDeclaredConstructor();
349     constructor.setAccessible(true);
350     T objToReturn = constructor.newInstance();
351     for (Field field : clazz.getDeclaredFields()) {
352       field.setAccessible(true);
353       Config fieldConfAnnot =
354           field.getAnnotation(Config.class);
355       if (fieldConfAnnot != null) {
356         if (field.getType().isPrimitive() || ConfigurationUtils.isWrapperClass(field.getType())
357             || (field.getType().isArray() && (field.getType().getComponentType().isPrimitive()
358             || ConfigurationUtils.isWrapperClass(field.getType().getComponentType())))
359             || field.getType().getAnnotation(Config.class) != null) {
360           field.set(objToReturn,
361               get(tenant, namespace, keyPrefix + fieldConfAnnot.key(), field.getType(), hints));
362         } else if (Collection.class.isAssignableFrom(field.getType())) {
363           Object obj = get(tenant, namespace, keyPrefix + fieldConfAnnot.key(),
364               ConfigurationUtils.getArrayClass(ConfigurationUtils.getCollectionGenericType(field)),
365               hints);
366           if (obj != null) {
367             List list = Arrays.asList((Object[]) obj);
368             Class clazzToInstantiate = null;
369             if (field.getType().isInterface()) {
370               clazzToInstantiate =
371                   ConfigurationUtils.getConcreteCollection(field.getType()).getClass();
372             } else if (Modifier.isAbstract(field.getType().getModifiers())) {
373               clazzToInstantiate =
374                   ConfigurationUtils.getCompatibleCollectionForAbstractDef(field.getType())
375                       .getClass();
376             } else {
377               clazzToInstantiate = field.getType();
378             }
379             Constructor construct =
380                 getConstructorWithArguments(clazzToInstantiate, Collection.class);
381             if (construct != null) {
382               construct.setAccessible(true);
383               field.set(objToReturn, construct.newInstance(list));
384             } else if ((construct =
385                 getConstructorWithArguments(clazzToInstantiate, Integer.class, Boolean.class,
386                     Collection.class)) != null) {
387               construct.setAccessible(true);
388               field.set(objToReturn, construct.newInstance(list.size(), true, list));
389             }
390           }
391         }else if (Map.class.isAssignableFrom(field.getType())){
392           field.set(objToReturn, generateMap(tenant, namespace, keyPrefix+fieldConfAnnot.key()));
393         }
394       }
395     }
396     return objToReturn;
397   }
398
399   private Constructor getConstructorWithArguments(Class clazz, Class... classes) {
400     try {
401       return clazz.getDeclaredConstructor(classes);
402     } catch (Exception exception) {
403       return null;
404     }
405   }
406
407   private Class getWrapperClass(Class clazz) {
408     if (byte.class == clazz) {
409       return Byte.class;
410     } else if (short.class == clazz) {
411       return Short.class;
412     } else if (int.class == clazz) {
413       return Integer.class;
414     } else if (long.class == clazz) {
415       return Long.class;
416     } else if (float.class == clazz) {
417       return Float.class;
418     } else if (double.class == clazz) {
419       return Double.class;
420     } else if (char.class == clazz) {
421       return Character.class;
422     } else if (boolean.class == clazz) {
423       return Boolean.class;
424     }
425     return clazz;
426   }
427
428   private <T> T getValue(Object obj, Class<T> clazz, int processingHint) {
429     if (obj == null || obj.toString().trim().length() == 0) {
430       return null;
431     } else {
432       obj = obj.toString().trim();
433     }
434     if (String.class.equals(clazz)) {
435       if (obj.toString().startsWith("@") && ConfigurationUtils.isExternalLookup(processingHint)) {
436         String contents = ConfigurationUtils
437             .getFileContents(NonConfigResource.locate(obj.toString().substring(1).trim()));
438         if (contents == null) {
439           contents = ConfigurationUtils.getFileContents(obj.toString().substring(1).trim());
440         }
441         if (contents != null) {
442           obj = contents;
443         }
444       }
445       return (T) obj.toString();
446     } else if (Number.class.isAssignableFrom(clazz)) {
447       Double doubleValue = Double.valueOf(obj.toString());
448       switch (clazz.getName()) {
449         case "java.lang.Byte":
450           Byte byteVal = doubleValue.byteValue();
451           return (T) byteVal;
452         case "java.lang.Short":
453           Short shortVal = doubleValue.shortValue();
454           return (T) shortVal;
455         case "java.lang.Integer":
456           Integer intVal = doubleValue.intValue();
457           return (T) intVal;
458         case "java.lang.Long":
459           Long longVal = doubleValue.longValue();
460           return (T) longVal;
461         case "java.lang.Float":
462           Float floatVal = doubleValue.floatValue();
463           return (T) floatVal;
464         case "java.lang.Double":
465           Double doubleVal = doubleValue;
466           return (T) doubleVal;
467         default:
468       }
469     } else if (Boolean.class.equals(clazz)) {
470       return (T) Boolean.valueOf(obj.toString());
471     } else if (Character.class.equals(clazz)) {
472       return (T) Character.valueOf(obj.toString().charAt(0));
473     }
474     return null;
475   }
476
477   private <T> T[] getZeroLengthArrayFor(Class<T> clazz) {
478     Object obj = null;
479     if (clazz == int.class) {
480       obj = new int[]{};
481     } else if (clazz == byte.class) {
482       obj = new byte[]{};
483     } else if (clazz == short.class) {
484       obj = new short[]{};
485     } else if (clazz == long.class) {
486       obj = new long[]{};
487     } else if (clazz == float.class) {
488       obj = new float[]{};
489     } else if (clazz == double.class) {
490       obj = new double[]{};
491     } else if (clazz == boolean.class) {
492       obj = new boolean[]{};
493     } else if (clazz == char.class) {
494       obj = new char[]{};
495     } else if (clazz == Byte.class) {
496       obj = new Byte[]{};
497     } else if (clazz == Short.class) {
498       obj = new Short[]{};
499     } else if (clazz == Integer.class) {
500       obj = new Integer[]{};
501     } else if (clazz == Long.class) {
502       obj = new Long[]{};
503     } else if (clazz == Float.class) {
504       obj = new Float[]{};
505     } else if (clazz == Double.class) {
506       obj = new Double[]{};
507     } else if (clazz == Boolean.class) {
508       obj = new Boolean[]{};
509     } else if (clazz == Character.class) {
510       obj = new Character[]{};
511     } else if (clazz == String.class) {
512       obj = new String[]{};
513     }
514     return (T[]) obj;
515   }
516
517   private <T> Collection<T> convert(String commaSaperatedValues, Class<T> clazz,
518                                     int processingHints) {
519     ArrayList<T> collection = new ArrayList<>();
520     for (String value : commaSaperatedValues.split(",")) {
521       try {
522         T type1 = getValue(value, clazz, processingHints);
523         if (type1 != null) {
524           collection.add(type1);
525         }
526       } catch (RuntimeException re) {
527         // do nothing
528       }
529     }
530     return collection;
531   }
532
533   /**
534    * Shutdown.
535    */
536   public void shutdown() {
537     if (changeNotifier != null) {
538       try {
539         changeNotifier.shutdown();
540       } catch (Exception exception) {
541         exception.printStackTrace();
542       }
543     }
544   }
545
546   @Override
547   public void removeConfigurationChangeListener(String tenant, String namespace, String key,
548                                                 ConfigurationChangeListener myself) {
549     tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase()
550         : Constants.DEFAULT_TENANT;
551     namespace =
552         ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase()
553             : Constants.DEFAULT_NAMESPACE;
554     if (key == null || key.trim().length() == 0) {
555       throw new IllegalArgumentException(KEY_CANNOT_BE_NULL);
556     }
557     try {
558       changeNotifier.stopNotificationTowards(tenant, namespace, key, myself);
559     } catch (Exception exception) {
560       exception.printStackTrace();
561     }
562   }
563
564   @Override
565   public <T> Map<String, T> populateMap(String tenantId, String namespace, String key, Class<T> clazz){
566     if (tenantId==null || tenantId.trim().length()==0){
567       tenantId = tenant.get();
568     }else{
569       tenantId = tenantId.toUpperCase();
570     }
571     if (namespace==null || namespace.trim().length()==0){
572       namespace = Constants.DEFAULT_NAMESPACE;
573     }else{
574       namespace = namespace.toUpperCase();
575     }
576     Map<String, T> map = new HashMap<>();
577     Iterator<String> keys ;
578     try {
579       keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
580       while(keys.hasNext()){
581         String k = keys.next();
582         if (k.startsWith(key+".")){
583           k = k.substring(key.length()+1);
584           String subkey = k.substring(0, k.indexOf("."));
585           if (!map.containsKey(subkey)){
586             map.put(subkey, get(tenantId, namespace, key+"."+subkey, clazz));
587           }
588         }
589       }
590     }catch (Exception e){
591       e.printStackTrace();
592     }
593     return map;
594   }
595
596   @Override
597   public Map generateMap(String tenantId, String namespace, String key){
598     if (tenantId==null || tenantId.trim().length()==0){
599       tenantId = tenant.get();
600     }else{
601       tenantId = tenantId.toUpperCase();
602     }
603     if (namespace==null || namespace.trim().length()==0){
604       namespace = Constants.DEFAULT_NAMESPACE;
605     }else{
606       namespace = namespace.toUpperCase();
607     }
608     Map map, parentMap = new HashMap<>();
609     Iterator<String> keys ;
610     try {
611       if (key==null || key.trim().length()==0){
612         keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys();
613       }else{
614         keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key);
615       }
616       while(keys.hasNext()){
617         map = parentMap;
618         String k = keys.next();
619
620         if (key!=null && key.trim().length()!=0 && !k.startsWith(key+".")){
621           continue;
622         }
623         String value = getAsString(tenantId, namespace, k);
624         if (key!=null && key.trim().length()!=0 && k.startsWith(key+".")){
625           k = k.substring(key.trim().length()+1);
626         }
627
628         while(k.contains(".")){
629           if (k.contains(".")){
630             String subkey = k.substring(0, k.indexOf("."));
631             k = k.substring(k.indexOf(".")+1);
632             if (!map.containsKey(subkey)){
633               map.put(subkey, map=new HashMap<>());
634             }else{
635               map = (Map)map.get(subkey);
636             }
637           }
638         }
639         map.put(k, value);
640       }
641     }catch (Exception e){
642       e.printStackTrace();
643     }
644     return parentMap;
645   }
646
647
648
649
650 }