964b8d1a2df2db10f0a059412794da713d7c9da4
[sdc.git] /
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 package org.onap.config.impl;
17
18 import static org.onap.config.ConfigurationUtils.isBlank;
19
20 import java.io.File;
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.Field;
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Modifier;
25 import java.net.URL;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.concurrent.atomic.AtomicReference;
36 import java.util.function.Predicate;
37 import java.util.stream.Collectors;
38 import org.apache.commons.configuration2.ex.ConfigurationException;
39 import org.onap.config.ConfigurationUtils;
40 import org.onap.config.Constants;
41 import org.onap.config.NonConfigResource;
42 import org.onap.config.api.Config;
43 import org.onap.config.api.Hint;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 public class ConfigurationImpl implements org.onap.config.api.Configuration {
48
49     private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationImpl.class);
50     private static final String KEY_CANNOT_BE_NULL = "Key can't be null.";
51     private static final NonConfigResource NON_CONFIG_RESOURCE = new NonConfigResource();
52     private static final Map<String, AggregateConfiguration> MODULE_CONFIG_STORE = new HashMap<>();
53
54     static {
55         if (!loadClassPathConfigurationsAndResources() || !loadAdditionalConfigurationsAndResources() || !loadTenantConfigurations()) {
56             throw new IllegalStateException("Failed to initialize configuration");
57         }
58         populateFinalConfigurationIncrementally(MODULE_CONFIG_STORE);
59         loadNodeSpecificConfigurations();
60     }
61
62     private static boolean loadClassPathConfigurationsAndResources() {
63         List<URL> classpathResources = ConfigurationUtils.getAllClassPathResources();
64         Predicate<URL> predicate = ConfigurationUtils::isConfig;
65         Map<Boolean, List<URL>> resources = classpathResources.stream().collect(Collectors.partitioningBy(predicate));
66         List<URL> configResources = resources.get(true);
67         List<URL> nonConfigResources = resources.get(false);
68         AtomicReference<Boolean> successFlagHolder = new AtomicReference<>(true);
69         configResources.forEach(url -> successFlagHolder.set(setUpdateModuleConfigStore(url)));
70         nonConfigResources.forEach(NON_CONFIG_RESOURCE::add);
71         return successFlagHolder.get();
72     }
73
74     private static boolean loadAdditionalConfigurationsAndResources() {
75         String configLocation = System.getProperty("config.location");
76         AtomicReference<Boolean> successFlagHolder = new AtomicReference<>(true);
77         if (!isBlank(configLocation)) {
78             File root = new File(configLocation);
79             Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
80             Predicate<File> filePredicate = ConfigurationUtils::isConfig;
81             Map<Boolean, List<File>> resources = filesystemResources.stream().collect(Collectors.partitioningBy(filePredicate));
82             List<File> configResources = resources.get(true);
83             List<File> nonConfigResources = resources.get(false);
84             configResources.forEach(file -> successFlagHolder.set(setUpdateModuleConfigStore(file)));
85             nonConfigResources.forEach(NON_CONFIG_RESOURCE::add);
86         }
87         return successFlagHolder.get();
88     }
89
90     private static boolean loadTenantConfigurations() {
91         String tenantConfigLocation = System.getProperty("tenant.config.location");
92         AtomicReference<Boolean> successFlagHolder = new AtomicReference<>(true);
93         if (!isBlank(tenantConfigLocation)) {
94             File root = new File(tenantConfigLocation);
95             Collection<File> tenantsRoot = ConfigurationUtils.getAllFiles(root, false, true);
96             Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
97             Map<Boolean, List<File>> resources = filesystemResources.stream().collect(Collectors.partitioningBy(ConfigurationUtils::isConfig));
98             Collection<File> tenantResources = resources.get(true);
99             tenantResources.forEach(configFile -> {
100                 AtomicReference<String> moduleNameHolder = new AtomicReference<>(ConfigurationUtils.getNamespace(configFile));
101                 Predicate<File> startsWithRootPredicate = tenantRoot -> configFile.getAbsolutePath().startsWith(tenantRoot.getAbsolutePath());
102                 Collection<File> matchesTenantRoot = tenantsRoot.stream().filter(startsWithRootPredicate)
103                     .collect(Collectors.toCollection(ArrayList::new));
104                 AtomicReference<String[]> altResource = new AtomicReference<>();
105                 matchesTenantRoot.forEach(file -> altResource.set(
106                     (file.getName().toUpperCase() + Constants.TENANT_NAMESPACE_SEPARATOR + moduleNameHolder.get())
107                         .split(Constants.TENANT_NAMESPACE_SEPARATOR)));
108                 successFlagHolder.set(setUpdateModuleConfigStore(configFile, altResource.get()));
109             });
110         }
111         return successFlagHolder.get();
112     }
113
114     private static void loadNodeSpecificConfigurations() {
115         String nodeConfigLocation = System.getProperty("node.config.location");
116         if (!isBlank(nodeConfigLocation)) {
117             File root = new File(nodeConfigLocation);
118             Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false);
119             filesystemResources.stream().filter(ConfigurationUtils::isConfig).forEach(file -> ConfigurationRepository.lookup()
120                 .populateOverrideConfiguration(ConfigurationUtils
121                     .getConfigurationRepositoryKey(ConfigurationUtils.getNamespace(file).split(Constants.TENANT_NAMESPACE_SEPARATOR)), file));
122         }
123     }
124
125     private static void populateFinalConfigurationIncrementally(Map<String, AggregateConfiguration> configs) {
126         if (configs.get(Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELIMITER + Constants.DB_NAMESPACE) != null) {
127             ConfigurationRepository.lookup()
128                 .populateConfiguration(Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELIMITER + Constants.DB_NAMESPACE,
129                     configs.remove(Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELIMITER + Constants.DB_NAMESPACE).getFinalConfiguration());
130         }
131         Set<String> modules = configs.keySet();
132         modules.forEach(m -> ConfigurationRepository.lookup().populateConfiguration(m, configs.get(m).getFinalConfiguration()));
133     }
134
135     private static <T> boolean setUpdateModuleConfigStore(T resource, String... namedResources) {
136         boolean success = true;
137         String moduleName;
138         try {
139             if (namedResources == null || namedResources.length == 0) {
140                 moduleName = getConfigurationRepositoryKeyWrapper(resource);
141             } else {
142                 moduleName = getConfigurationRepositoryKeyWrapper(namedResources);
143             }
144             moduleAddConfigWrapper(moduleName, resource);
145         } catch (Exception e) {
146             success = false;
147             LOGGER.error("Error occurred while processing config resource {}", resource, e);
148         }
149         return success;
150     }
151
152     private static <T> String getConfigurationRepositoryKeyWrapper(T resource) throws ConfigurationException {
153         switch (resource.getClass().getSimpleName()) {
154             case "URL":
155                 return ConfigurationUtils.getConfigurationRepositoryKey((URL) resource);
156             case "File":
157                 return ConfigurationUtils.getConfigurationRepositoryKey((File) resource);
158             case "String[]":
159                 return ConfigurationUtils.getConfigurationRepositoryKey((String[]) resource);
160             default:
161                 throw new ConfigurationException("Unsupported resource type.");
162         }
163     }
164
165     private static <T> void moduleAddConfigWrapper(String moduleName, T resource) throws ConfigurationException {
166         AggregateConfiguration moduleConfig = MODULE_CONFIG_STORE.get(moduleName);
167         if (moduleConfig == null) {
168             moduleConfig = new AggregateConfiguration();
169             MODULE_CONFIG_STORE.put(moduleName, moduleConfig);
170         }
171         switch (resource.getClass().getSimpleName()) {
172             case "URL":
173                 moduleConfig.addConfig((URL) resource);
174                 break;
175             case "File":
176                 moduleConfig.addConfig((File) resource);
177                 break;
178             default:
179                 throw new ConfigurationException("Unsupported resource type.");
180         }
181     }
182
183     private static String calculateNamespace(String namespace) {
184         if (isBlank(namespace)) {
185             return Constants.DEFAULT_NAMESPACE;
186         }
187         return namespace.toUpperCase();
188     }
189
190     private static String calculateTenant(String tenant) {
191         if (isBlank(tenant)) {
192             return Constants.DEFAULT_TENANT;
193         }
194         return tenant.toUpperCase();
195     }
196
197     @Override
198     public <T> T get(String tenant, String namespace, String key, Class<T> clazz, Hint... hints) {
199         String[] tenantNamespaceArray;
200         if (tenant == null && namespace != null) {
201             tenantNamespaceArray = namespace.split(Constants.TENANT_NAMESPACE_SEPARATOR);
202             if (tenantNamespaceArray.length > 1) {
203                 tenant = tenantNamespaceArray[0];
204                 namespace = tenantNamespaceArray[1];
205             }
206         }
207         tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase() : Constants.DEFAULT_TENANT;
208         namespace = ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase() : Constants.DEFAULT_NAMESPACE;
209         hints = hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC} : hints;
210         T returnValue;
211         returnValue = getInternal(tenant, namespace, key, clazz, hints);
212         if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue)) && !Constants.DEFAULT_TENANT.equals(tenant)) {
213             returnValue = getInternal(Constants.DEFAULT_TENANT, namespace, key, clazz, hints);
214         }
215         if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue)) && !Constants.DEFAULT_NAMESPACE.equals(namespace)) {
216             returnValue = getInternal(tenant, Constants.DEFAULT_NAMESPACE, key, clazz, hints);
217         }
218         if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue)) && !Constants.DEFAULT_NAMESPACE.equals(namespace)
219             && !Constants.DEFAULT_TENANT.equals(tenant)) {
220             returnValue = getInternal(Constants.DEFAULT_TENANT, Constants.DEFAULT_NAMESPACE, key, clazz, hints);
221         }
222         if (returnValue == null && ConfigurationUtils.isAPrimitive(clazz)) {
223             returnValue = (T) ConfigurationUtils.getDefaultFor(clazz);
224         }
225         return returnValue;
226     }
227
228     @Override
229     public <T> Map<String, T> populateMap(String tenantId, String namespace, String key, Class<T> clazz) {
230         final String calculatedTenantId = calculateTenant(tenantId);
231         final String calculatedNamespace = calculateNamespace(namespace);
232         Map<String, T> map = new HashMap<>();
233         Iterator<String> keys;
234         try {
235             keys = ConfigurationRepository.lookup().getConfigurationFor(calculatedTenantId, calculatedNamespace).getKeys(key);
236             keys.forEachRemaining(k -> {
237                 if (k.startsWith(key + ".")) {
238                     k = k.substring(key.length() + 1);
239                     String subkey = k.substring(0, k.indexOf('.'));
240                     if (!map.containsKey(subkey)) {
241                         map.put(subkey, get(calculatedTenantId, calculatedNamespace, key + "." + subkey, clazz));
242                     }
243                 }
244             });
245         } catch (Exception e) {
246             LOGGER.warn("Couldn't populate map fot tenant: {}, namespace: {}, key: {}, type: {}", tenantId, namespace, key, clazz.getSimpleName(), e);
247         }
248         return map;
249     }
250
251     @Override
252     public Map<Object, Object> generateMap(String tenantId, String namespace, String key) {
253         final String calculatedTenantId = calculateTenant(tenantId);
254         final String calculatedNamespace = calculateNamespace(namespace);
255         Map<Object, Object> parentMap = new HashMap<>();
256         Iterator<String> configKeys;
257         try {
258             if (isBlank(key)) {
259                 configKeys = ConfigurationRepository.lookup().getConfigurationFor(calculatedTenantId, calculatedNamespace).getKeys();
260             } else {
261                 configKeys = ConfigurationRepository.lookup().getConfigurationFor(calculatedTenantId, calculatedNamespace).getKeys(key);
262             }
263             configKeys.forEachRemaining(subKey -> {
264                 if (!isBlank(key) && !subKey.startsWith(key + ".")) {
265                     configKeys.remove();
266                 }
267                 parseConfigSubKeys(subKey, key, calculatedTenantId, calculatedNamespace, parentMap);
268             });
269         } catch (Exception e) {
270             LOGGER.warn("Couldn't generate map fot tenant: {}, namespace: {}, key: {}", tenantId, namespace, key, e);
271         }
272         return parentMap;
273     }
274
275     private void parseConfigSubKeys(String subKey, String keyPrefix, String tenantId, String namespace, Map<Object, Object> targetMap) {
276         String value = getAsString(tenantId, namespace, subKey);
277         if (!isBlank(keyPrefix) && subKey.startsWith(keyPrefix + ".")) {
278             subKey = subKey.substring(keyPrefix.trim().length() + 1);
279         }
280         while (subKey.contains(".")) {
281             String subSubKey = subKey.substring(0, subKey.indexOf('.'));
282             subKey = subKey.substring(subKey.indexOf('.') + 1);
283             if (!targetMap.containsKey(subSubKey)) {
284                 Map<Object, Object> subMap = new HashMap<>();
285                 targetMap.put(subSubKey, subMap);
286                 targetMap = subMap;
287             } else {
288                 targetMap = (Map<Object, Object>) targetMap.get(subSubKey);
289             }
290         }
291         targetMap.put(subKey, value);
292     }
293
294     protected <T> T getInternal(String tenant, String namespace, String key, Class<T> clazz, Hint... hints) {
295         int processingHints = Hint.DEFAULT.value();
296         if (hints != null) {
297             for (Hint hint : hints) {
298                 processingHints = processingHints | hint.value();
299             }
300         }
301         tenant = calculateTenant(tenant);
302         namespace = calculateNamespace(namespace);
303         if (isBlank(key) && !clazz.isAnnotationPresent(Config.class)) {
304             throw new IllegalArgumentException(KEY_CANNOT_BE_NULL);
305         }
306         if (clazz == null) {
307             throw new IllegalArgumentException("clazz is null.");
308         }
309         if (ConfigurationUtils.isAPrimitive(clazz)) {
310             clazz = getWrapperClass(clazz);
311         }
312         try {
313             if (ConfigurationUtils.isWrapperClass(clazz)) {
314                 return getWrapperTypeValue(tenant, namespace, key, clazz, processingHints);
315             } else if (ConfigurationUtils.isAPrimitivesOrWrappersArray(clazz)) {
316                 return getArrayTypeValue(tenant, namespace, key, clazz, processingHints);
317             } else if (clazz.isAnnotationPresent(Config.class)) {
318                 return getAnnotatedTypeValue(tenant, namespace, clazz, isBlank(key) ? "" : (key + "."), hints);
319             } else {
320                 throw new IllegalArgumentException("Only primitive classes, wrapper classes, corresponding array classes and any "
321                     + "class decorated with @org.openecomp.config.api.Config are allowed as argument.");
322             }
323         } catch (Exception exception) {
324             LOGGER
325                 .warn("Failed to get internal value fot tenant: {}, namespace: {}, key: {}, type: {}", tenant, namespace, key, clazz.getSimpleName(),
326                     exception);
327         }
328         return null;
329     }
330
331     private <T> T getWrapperTypeValue(String tenant, String namespace, String key, Class<T> clazz, int processingHints) throws Exception {
332         Object obj = ConfigurationUtils.getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace), key, processingHints);
333         if (obj != null) {
334             if (ConfigurationUtils.isCollection(obj.toString())) {
335                 obj = ConfigurationUtils.getCollectionString(obj.toString());
336             }
337             String value = ConfigurationUtils.processVariablesIfPresent(tenant, namespace, obj.toString().split(",")[0]);
338             return (T) getTypeValue(value, clazz, processingHints);
339         }
340         return null;
341     }
342
343     private <T> T getArrayTypeValue(String tenant, String namespace, String key, Class<T> clazz, int processingHints) throws Exception {
344         Object obj = ConfigurationUtils.getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace), key, processingHints);
345         if (obj != null) {
346             Class componentType = clazz.getComponentType();
347             if (ConfigurationUtils.isAPrimitivesArray(clazz)) {
348                 componentType = getWrapperClass(componentType);
349             }
350             String collString = ConfigurationUtils.getCollectionString(obj.toString());
351             ArrayList<String> tempCollection = new ArrayList<>();
352             for (String itemValue : collString.split(",")) {
353                 tempCollection.add(ConfigurationUtils.processVariablesIfPresent(tenant, namespace, itemValue));
354             }
355             Collection<T> collection = convert(ConfigurationUtils.getCollectionString(Arrays.toString(tempCollection.toArray())),
356                 (Class<T>) componentType, processingHints);
357             if (ConfigurationUtils.isAPrimitivesArray(clazz)) {
358                 return (T) ConfigurationUtils.getPrimitiveArray(collection, componentType);
359             } else {
360                 return (T) collection.toArray(getZeroLengthArrayFor(getWrapperClass(componentType)));
361             }
362         } else {
363             return null;
364         }
365     }
366
367     private <T> T getAnnotatedTypeValue(String tenant, String namespace, Class<T> clazz, String keyPrefix, Hint... hints)
368         throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
369         Config confAnnotation = clazz.getAnnotation(Config.class);
370         if (confAnnotation != null && confAnnotation.key().length() > 0 && !keyPrefix.endsWith(".")) {
371             keyPrefix += (confAnnotation.key() + ".");
372         }
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             Config fieldConfAnnotation = field.getAnnotation(Config.class);
379             Class<?> fieldType = field.getType();
380             if (fieldConfAnnotation == null) {
381                 continue;
382             }
383             if (ConfigurationUtils.isAPrimitiveOrWrapper(fieldType) || ConfigurationUtils.isAPrimitivesOrWrappersArray(fieldType)) {
384                 setPrimitiveField(field, objToReturn, tenant, namespace, keyPrefix, hints);
385             }
386             if (ConfigurationUtils.isACollection(fieldType)) {
387                 setCollectionField(field, objToReturn, tenant, namespace, keyPrefix, hints);
388             }
389             if (ConfigurationUtils.isAMap(fieldType)) {
390                 setMapField(field, objToReturn, tenant, namespace, keyPrefix);
391             }
392         }
393         return objToReturn;
394     }
395
396     private void setPrimitiveField(Field field, Object objToReturn, String tenant, String namespace, String keyPrefix, Hint[] hints)
397         throws IllegalAccessException {
398         String fieldConfAnnotationKey = field.getAnnotation(Config.class).key();
399         Class<?> fieldType = field.getType();
400         field.set(objToReturn, get(tenant, namespace, keyPrefix + fieldConfAnnotationKey, fieldType, hints));
401     }
402
403     private void setMapField(Field field, Object objToReturn, String tenant, String namespace, String keyPrefix) throws IllegalAccessException {
404         String fieldConfAnnotationKey = field.getAnnotation(Config.class).key();
405         field.set(objToReturn, generateMap(tenant, namespace, keyPrefix + fieldConfAnnotationKey));
406     }
407
408     private void setCollectionField(Field field, Object objToReturn, String tenant, String namespace, String keyPrefix, Hint[] hints)
409         throws IllegalAccessException, InvocationTargetException, InstantiationException {
410         String fieldConfAnnotationKey = field.getAnnotation(Config.class).key();
411         Class<?> fieldType = field.getType();
412         Object obj = get(tenant, namespace, keyPrefix + fieldConfAnnotationKey,
413             ConfigurationUtils.getArrayClass(ConfigurationUtils.getCollectionGenericType(field)), hints);
414         if (obj == null) {
415             return;
416         }
417         List<Object> list = Arrays.asList((Object[]) obj);
418         Class clazzToInstantiate;
419         if (fieldType.isInterface()) {
420             clazzToInstantiate = ConfigurationUtils.getConcreteCollection(fieldType).getClass();
421         } else if (Modifier.isAbstract(fieldType.getModifiers())) {
422             clazzToInstantiate = ConfigurationUtils.getCompatibleCollectionForAbstractDef(fieldType).getClass();
423         } else {
424             clazzToInstantiate = fieldType;
425         }
426         Constructor construct = getConstructorWithArguments(clazzToInstantiate, Collection.class);
427         if (construct != null) {
428             construct.setAccessible(true);
429             field.set(objToReturn, construct.newInstance(list));
430         } else {
431             construct = getConstructorWithArguments(clazzToInstantiate, Integer.class, Boolean.class, Collection.class);
432             if (construct != null) {
433                 construct.setAccessible(true);
434                 field.set(objToReturn, construct.newInstance(list.size(), true, list));
435             }
436         }
437     }
438
439     private Constructor getConstructorWithArguments(Class<?> clazz, Class<?>... classes) {
440         try {
441             return clazz.getDeclaredConstructor(classes);
442         } catch (Exception exception) {
443             LOGGER.warn("Failed to get {} constructor.", clazz.getSimpleName(), exception);
444             return null;
445         }
446     }
447
448     private Class getWrapperClass(Class<?> clazz) {
449         if (byte.class == clazz) {
450             return Byte.class;
451         } else if (short.class == clazz) {
452             return Short.class;
453         } else if (int.class == clazz) {
454             return Integer.class;
455         } else if (long.class == clazz) {
456             return Long.class;
457         } else if (float.class == clazz) {
458             return Float.class;
459         } else if (double.class == clazz) {
460             return Double.class;
461         } else if (char.class == clazz) {
462             return Character.class;
463         } else if (boolean.class == clazz) {
464             return Boolean.class;
465         }
466         return clazz;
467     }
468
469     private <T> T getTypeValue(Object obj, Class<T> clazz, int processingHint) {
470         if (obj == null || obj.toString().trim().length() == 0) {
471             return null;
472         } else {
473             obj = obj.toString().trim();
474         }
475         if (String.class.equals(clazz)) {
476             return getValueForStringType(obj, processingHint);
477         }
478         if (Number.class.isAssignableFrom(clazz)) {
479             return getValueForNumbersType(obj, clazz);
480         }
481         if (Boolean.class.equals(clazz)) {
482             return (T) Boolean.valueOf(obj.toString());
483         }
484         if (Character.class.equals(clazz)) {
485             return (T) Character.valueOf(obj.toString().charAt(0));
486         }
487         return null;
488     }
489
490     private <T> T getValueForStringType(Object obj, int processingHint) {
491         if (obj.toString().startsWith("@") && ConfigurationUtils.isExternalLookup(processingHint)) {
492             String subString = obj.toString().substring(1).trim();
493             String contents = ConfigurationUtils.getFileContents(NON_CONFIG_RESOURCE.locate(subString));
494             if (contents == null) {
495                 contents = ConfigurationUtils.getFileContents(subString);
496             }
497             if (contents != null) {
498                 obj = contents;
499             }
500         }
501         return (T) obj.toString();
502     }
503
504     private <T> T getValueForNumbersType(Object obj, Class<T> clazz) {
505         Double doubleValue = Double.valueOf(obj.toString());
506         switch (clazz.getName()) {
507             case "java.lang.Byte":
508                 Byte byteVal = doubleValue.byteValue();
509                 return (T) byteVal;
510             case "java.lang.Short":
511                 Short shortVal = doubleValue.shortValue();
512                 return (T) shortVal;
513             case "java.lang.Integer":
514                 Integer intVal = doubleValue.intValue();
515                 return (T) intVal;
516             case "java.lang.Long":
517                 Long longVal = doubleValue.longValue();
518                 return (T) longVal;
519             case "java.lang.Float":
520                 Float floatVal = doubleValue.floatValue();
521                 return (T) floatVal;
522             case "java.lang.Double":
523                 return (T) doubleValue;
524             default:
525                 return null;
526         }
527     }
528
529     private <T> T[] getZeroLengthArrayFor(Class<T> clazz) {
530         Object objToReturn = null;
531         if (ConfigurationUtils.isAPrimitive(clazz)) {
532             objToReturn = ConfigurationUtils.getPrimitiveArray(Collections.emptyList(), clazz);
533         } else if (ConfigurationUtils.isWrapperClass(clazz)) {
534             objToReturn = ConfigurationUtils.getWrappersArray(Collections.emptyList(), clazz);
535         }
536         return (T[]) objToReturn;
537     }
538
539     private <T> Collection<T> convert(String commaSeparatedValues, Class<T> clazz, int processingHints) {
540         ArrayList<T> collection = new ArrayList<>();
541         for (String value : commaSeparatedValues.split(",")) {
542             try {
543                 T type1 = getTypeValue(value, clazz, processingHints);
544                 if (type1 != null) {
545                     collection.add(type1);
546                 }
547             } catch (RuntimeException re) {
548                 LOGGER.warn("Failed to convert {}", commaSeparatedValues, re);
549             }
550         }
551         return collection;
552     }
553 }