2 * Copyright © 2016-2018 European Support Limited
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 * Modifications Copyright (c) 2019 Samsung
20 package org.onap.config;
22 import com.virtlink.commons.configuration2.jackson.JsonConfiguration;
23 import io.github.classgraph.ClassGraph;
24 import io.github.classgraph.ScanResult;
25 import org.apache.commons.configuration2.Configuration;
26 import org.apache.commons.configuration2.CompositeConfiguration;
27 import org.apache.commons.configuration2.FileBasedConfiguration;
28 import org.apache.commons.configuration2.PropertiesConfiguration;
29 import org.apache.commons.configuration2.XMLConfiguration;
30 import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
31 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
32 import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
33 import org.apache.commons.configuration2.builder.fluent.Configurations;
34 import org.apache.commons.configuration2.builder.fluent.Parameters;
35 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
36 import org.apache.commons.configuration2.ex.ConfigurationException;
37 import org.apache.commons.io.IOUtils;
38 import org.onap.config.api.Config;
39 import org.onap.config.api.ConfigurationManager;
40 import org.onap.config.impl.YamlConfiguration;
41 import org.onap.config.type.ConfigurationMode;
42 import org.onap.config.type.ConfigurationType;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
47 import java.io.IOException;
48 import java.lang.reflect.Array;
49 import java.lang.reflect.Field;
50 import java.lang.reflect.ParameterizedType;
51 import java.lang.reflect.Type;
52 import java.net.MalformedURLException;
54 import java.nio.charset.Charset;
55 import java.nio.file.Files;
56 import java.nio.file.FileVisitResult;
57 import java.nio.file.Path;
58 import java.nio.file.SimpleFileVisitor;
59 import java.nio.file.attribute.BasicFileAttributes;
60 import java.util.ArrayDeque;
61 import java.util.ArrayList;
62 import java.util.Arrays;
63 import java.util.Collection;
64 import java.util.Collections;
65 import java.util.Deque;
66 import java.util.HashMap;
67 import java.util.HashSet;
68 import java.util.List;
70 import java.util.Objects;
71 import java.util.Optional;
72 import java.util.Queue;
74 import java.util.SortedSet;
75 import java.util.TreeSet;
76 import java.util.concurrent.BlockingQueue;
77 import java.util.concurrent.ConcurrentLinkedQueue;
78 import java.util.concurrent.LinkedBlockingQueue;
79 import java.util.concurrent.LinkedTransferQueue;
80 import java.util.concurrent.TransferQueue;
81 import java.util.function.Predicate;
82 import java.util.regex.Matcher;
83 import java.util.regex.Pattern;
84 import java.util.stream.Collectors;
86 import static java.util.Optional.ofNullable;
87 import static org.onap.config.api.Hint.EXTERNAL_LOOKUP;
88 import static org.onap.config.api.Hint.LATEST_LOOKUP;
89 import static org.onap.config.api.Hint.NODE_SPECIFIC;
91 public class ConfigurationUtils {
93 private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationUtils.class);
95 private static final String CONFIGURATION_TYPE_NOT_SUPPORTED = "Configuration type not supported:";
97 private static final Map<Class<?>, Class<?>> ARRAY_CLASS_MAP;
99 private static final String CONFIG_REGEX_TPL_OPT_1 = "CONFIG(-\\w*){0,1}(-(%s|%s|%s)){0,1}\\.(%s|%s|%s|%s)$";
101 private static final String CONFIG_REGEX_TPL_OPT_2 = "CONFIG(.)*\\.(%s|%s|%s|%s)$";
104 Map<Class<?>, Class<?>> arrayTypes = new HashMap<>();
105 arrayTypes.put(Byte.class, Byte[].class);
106 arrayTypes.put(Short.class, Short[].class);
107 arrayTypes.put(Integer.class, Integer[].class);
108 arrayTypes.put(Long.class, Long[].class);
109 arrayTypes.put(Float.class, Float[].class);
110 arrayTypes.put(Double.class, Double[].class);
111 arrayTypes.put(Boolean.class, Boolean[].class);
112 arrayTypes.put(Character.class, Character[].class);
113 arrayTypes.put(String.class, String[].class);
114 ARRAY_CLASS_MAP = Collections.unmodifiableMap(arrayTypes);
117 private ConfigurationUtils() {
118 // prevent instantiation
121 public static Collection<File> getAllFiles(File file, boolean recursive, boolean onlyDirectory) {
122 ArrayList<File> collection = new ArrayList<>();
123 Path rootPath = file.toPath();
125 Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
127 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
128 super.preVisitDirectory(dir,attrs);
129 if (rootPath.equals(dir)) {
130 return FileVisitResult.CONTINUE;
132 collection.add(dir.toFile());
133 return recursive? FileVisitResult.CONTINUE : FileVisitResult.SKIP_SUBTREE;
137 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
138 super.visitFile(file, attrs);
139 if (!onlyDirectory) {
140 collection.add(file.toFile());
142 return FileVisitResult.CONTINUE;
145 } catch (IOException e) {
146 LOGGER.error("Failed to walk through directories starting from: {}.", file.toString(), e);
151 public static String getCommaSeparatedList(String[] list) {
152 return (list == null) || (list.length == 0) ? "" : getCommaSeparatedList(Arrays.asList(list));
155 public static String getCommaSeparatedList(List<?> list) {
157 if ((list == null) || list.isEmpty()) {
161 return list.stream().filter(o -> o != null && !o.toString().trim().isEmpty())
162 .map(o -> o.toString().trim()).collect(Collectors.joining(","));
165 public static boolean isConfig(URL url) {
166 return isConfig(url.getFile());
169 public static boolean isConfig(String file) {
170 file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
171 file = file.substring(file.lastIndexOf('/') + 1);
174 CONFIG_REGEX_TPL_OPT_1,
175 ConfigurationMode.OVERRIDE,
176 ConfigurationMode.MERGE,
177 ConfigurationMode.UNION,
178 ConfigurationType.PROPERTIES.name(),
179 ConfigurationType.XML.name(),
180 ConfigurationType.JSON.name(),
181 ConfigurationType.YAML.name()
185 CONFIG_REGEX_TPL_OPT_2,
186 ConfigurationType.PROPERTIES.name(),
187 ConfigurationType.XML.name(),
188 ConfigurationType.JSON.name(),
189 ConfigurationType.YAML.name()
194 public static boolean isConfig(File file) {
195 return file != null && file.exists() && isConfig(file.getName());
198 private static Optional<String> readNamespace(Configuration config) {
199 return ofNullable(config).flatMap(configuration -> ofNullable(configuration.getString(Constants.NAMESPACE_KEY)))
200 .map(String::toUpperCase);
203 private static Optional<String> readMergeStrategy(Configuration config) {
204 return ofNullable(config).flatMap(configuration -> ofNullable(configuration.getString(Constants.MODE_KEY)))
205 .map(String::toUpperCase);
208 public static ConfigurationMode getMergeStrategy(File file) {
209 Optional<ConfigurationMode> configurationMode =
210 getConfiguration(file).flatMap(ConfigurationUtils::readMergeStrategy)
211 .flatMap(ConfigurationUtils::convertConfigurationMode);
212 return configurationMode.orElseGet(() -> getMergeStrategy(file.getName().toUpperCase()));
215 public static ConfigurationMode getMergeStrategy(URL url) {
216 Optional<ConfigurationMode> configurationMode =
217 getConfiguration(url).flatMap(ConfigurationUtils::readMergeStrategy)
218 .flatMap(ConfigurationUtils::convertConfigurationMode);
219 return configurationMode.orElseGet(() -> getMergeStrategy(url.getFile().toUpperCase()));
222 public static ConfigurationMode getMergeStrategy(String file) {
224 file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
225 file = file.substring(file.lastIndexOf('/') + 1);
226 Pattern pattern = Pattern.compile(
228 CONFIG_REGEX_TPL_OPT_1,
229 ConfigurationMode.OVERRIDE,
230 ConfigurationMode.MERGE,
231 ConfigurationMode.UNION,
232 ConfigurationType.PROPERTIES.name(),
233 ConfigurationType.XML.name(),
234 ConfigurationType.JSON.name(),
235 ConfigurationType.YAML.name()
238 Matcher matcher = pattern.matcher(file);
239 boolean b1 = matcher.matches();
241 for (int i = 1; i <= matcher.groupCount(); i++) {
242 String modeName = matcher.group(i);
243 if (modeName != null) {
244 modeName = modeName.substring(1);
247 return Enum.valueOf(ConfigurationMode.class, modeName);
248 } catch (Exception exception) {
249 LOGGER.debug("Configuration mode for merge strategy '{}' not found", modeName, exception);
257 public static Optional<FileBasedConfiguration> getConfiguration(URL url) {
261 ConfigurationType configType = ConfigurationUtils.getConfigType(url);
262 switch (configType) {
264 return Optional.of(new Configurations().fileBased(PropertiesConfiguration.class, url));
266 return Optional.of(new Configurations().fileBased(XMLConfiguration.class, url));
268 return Optional.of(new Configurations().fileBased(JsonConfiguration.class, url));
270 return Optional.of(new Configurations().fileBased(YamlConfiguration.class, url));
272 throw new ConfigurationException(CONFIGURATION_TYPE_NOT_SUPPORTED + configType);
274 } catch (ConfigurationException exception) {
275 LOGGER.error("Error reading configuration at {}.", url.toString(), exception);
278 return Optional.empty();
281 public static Optional<FileBasedConfiguration> getConfiguration(File file) {
284 return getConfiguration(file.getAbsoluteFile().toURI().toURL());
285 } catch (MalformedURLException e) {
286 throw new IllegalStateException("Malformed URL: " + file.getAbsolutePath());
290 public static ConfigurationType getConfigType(File file) {
291 Objects.requireNonNull(file, "File cannot be null");
292 return Enum.valueOf(ConfigurationType.class,
293 file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf('.') + 1).toUpperCase());
296 public static ConfigurationType getConfigType(URL url) {
297 Objects.requireNonNull(url, "URL cannot be null");
298 return Enum.valueOf(ConfigurationType.class,
299 url.getFile().substring(url.getFile().lastIndexOf('.') + 1).toUpperCase());
302 private static Optional<ConfigurationMode> convertConfigurationMode(String configMode) {
303 ConfigurationMode configurationMode = null;
305 configurationMode = ConfigurationMode.valueOf(configMode);
306 } catch (Exception exception) {
307 LOGGER.error("Could not find convert {} into configuration mode.", configMode, exception);
309 return Optional.ofNullable(configurationMode);
312 public static Class<?> getCollectionGenericType(Field field) {
313 Type type = field.getGenericType();
315 if (type instanceof ParameterizedType) {
317 ParameterizedType paramType = (ParameterizedType) type;
318 Type[] arr = paramType.getActualTypeArguments();
319 if (arr.length > 0) {
320 Class<?> clazz = (Class<?>) arr[0];
321 if (isWrapperClass(clazz)) {
324 throw new IllegalArgumentException("Collection of type " + clazz.getName() + " not supported.");
329 return String[].class;
332 public static boolean isWrapperClass(Class<?> clazz) {
333 Predicate<Class<?>> predicateWrapper = type -> type == String.class || type == Boolean.class || type == Character.class
334 || Number.class.isAssignableFrom(type);
335 return isA(predicateWrapper, clazz);
338 public static boolean isAPrimitive(Class<?> clazz) {
339 return isA(Class::isPrimitive, clazz);
343 * Check if clazz implementing Map iface
345 public static boolean isAMap(Class<?> clazz) {
346 Predicate<Class<?>> predicateMap = Map.class::isAssignableFrom;
347 return isA(predicateMap, clazz);
351 * Check if clazz implementing Collection iface
353 public static boolean isACollection(Class<?> clazz) {
354 Predicate<Class<?>> predicateCollection = Collection.class::isAssignableFrom;
355 return isA(predicateCollection, clazz);
359 * Check if clazz is a primitive or primitive wrapper
361 public static boolean isAPrimitiveOrWrapper(Class<?> clazz) {
362 Predicate<Class<?>> predicatePrimitive = Class::isPrimitive;
363 Predicate<Class<?>> predicateWrapper = ConfigurationUtils::isWrapperClass;
364 return isA(predicatePrimitive.or(predicateWrapper), clazz);
368 * Check if clazz is array of primitives or array of primitives wrappers
370 public static boolean isAPrimitivesOrWrappersArray(Class<?> clazz) {
371 Predicate<Class<?>> predicatePrimitivesOrWrappersArray =
372 type -> ConfigurationUtils.isAWrappersArray(type) || ConfigurationUtils.isAPrimitivesArray(type);
373 return isA(predicatePrimitivesOrWrappersArray, clazz);
378 * Check is clazz is array of primitives
380 public static boolean isAPrimitivesArray(Class<?> clazz) {
381 Predicate<Class<?>> predicateArray = Class::isArray;
382 Predicate<Class<?>> predicateComponentPrimitive = type -> type.getComponentType().isPrimitive();
383 return isA(predicateArray.and(predicateComponentPrimitive), clazz);
387 * Check is clazz is array of primitives wrappers
389 public static boolean isAWrappersArray(Class<?> clazz) {
390 Predicate<Class<?>> predicateArray = Class::isArray;
391 Predicate<Class<?>> predicateComponentWrapper = type -> isWrapperClass(type.getComponentType());
392 return isA(predicateArray.and(predicateComponentWrapper), clazz);
395 private static boolean isA(Predicate<Class<?>> predicate, Class<?> clazz) {
396 return predicate.test(clazz);
399 public static Class<?> getArrayClass(Class<?> clazz) {
400 return ARRAY_CLASS_MAP.getOrDefault(clazz, null);
403 public static List<URL> getAllClassPathResources() {
404 try (ScanResult scanResult = new ClassGraph().scan()) {
405 return scanResult.getAllResources().getURLs();
409 public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(File file) {
410 FileBasedConfigurationBuilder<FileBasedConfiguration> builder;
411 ConfigurationType configType = ConfigurationUtils.getConfigType(file);
412 builder = getFileBasedConfigurationBuilder(configType);
413 builder.configure(new Parameters().fileBased().setFile(file)
414 .setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
418 public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(URL url) {
419 ConfigurationType configType = ConfigurationUtils.getConfigType(url);
420 ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder =
421 getFileBasedConfigurationBuilder(configType);
423 new Parameters().fileBased().setURL(url).setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
427 private static ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> getFileBasedConfigurationBuilder(
428 ConfigurationType configType) {
430 ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder;
431 switch (configType) {
433 builder = new ReloadingFileBasedConfigurationBuilder<>(PropertiesConfiguration.class);
436 builder = new ReloadingFileBasedConfigurationBuilder<>(XMLConfiguration.class);
439 builder = new ReloadingFileBasedConfigurationBuilder<>(JsonConfiguration.class);
442 builder = new ReloadingFileBasedConfigurationBuilder<>(YamlConfiguration.class);
445 throw new IllegalArgumentException(CONFIGURATION_TYPE_NOT_SUPPORTED + configType);
450 public static <T> T read(Configuration config, Class<T> clazz, String keyPrefix) throws Exception {
451 Config confAnnotation = clazz.getAnnotation(Config.class);
452 if (confAnnotation != null) {
453 keyPrefix += (confAnnotation.key() + ".");
455 T objToReturn = clazz.newInstance();
456 for (Field field : clazz.getDeclaredFields()) {
457 Config fieldAnnotation = field.getAnnotation(Config.class);
458 if (fieldAnnotation != null) {
459 field.setAccessible(true);
460 field.set(objToReturn, config.getProperty(keyPrefix + fieldAnnotation.key()));
461 } else if (field.getType().getAnnotation(Config.class) != null) {
462 field.set(objToReturn, read(config, field.getType(), keyPrefix));
468 public static Object getPrimitiveArray(Collection<?> collection, Class<?> clazz) {
469 switch (clazz.getName()) {
471 return getIntsPrimitiveArray(collection);
473 return getBytesPrimitiveArray(collection);
475 return getShortsPrimitiveArray(collection);
477 return getLongsPrimitiveArray(collection);
479 return getFloatsPrimitiveArray(collection);
481 return getDoublesPrimitiveArray(collection);
483 return getBooleansPrimitiveArray(collection);
485 return getCharsPrimitiveArray(collection);
491 public static Object getWrappersArray(Collection<?> collection, Class<?> clazz) {
493 if (isWrapperClass(clazz)){
494 int collectionSize = collection.size();
495 array = Array.newInstance(clazz, collection.size());
496 Object[] objArray = collection.toArray();
497 System.arraycopy(objArray, 0, array, 0, collectionSize);
502 public static String getCollectionString(String input) {
503 Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
504 Matcher matcher = pattern.matcher(input);
505 if (matcher.matches()) {
506 input = matcher.group(1);
511 public static String processVariablesIfPresent(String tenant, String namespace, String data) {
512 Pattern pattern = Pattern.compile("^.*\\$\\{(.*)\\}.*");
513 Matcher matcher = pattern.matcher(data);
514 if (matcher.matches()) {
515 final int substringStartIndex = 4;
516 String key = matcher.group(1);
518 if (key.toUpperCase().startsWith("ENV:")) {
519 value = System.getenv(key.substring(substringStartIndex));
520 } else if (key.toUpperCase().startsWith("SYS:")) {
521 value = System.getProperty(key.substring(substringStartIndex));
523 value = ConfigurationUtils.getCollectionString(
524 ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key).toString());
526 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "}",
527 value == null ? "" : value.replace("\\", "\\\\")));
533 public static String getFileContents(String path) {
536 return IOUtils.toString(new URL(path), Charset.defaultCharset());
538 } catch (Exception exception) {
539 LOGGER.error("Error while getting '{}' content", path, exception);
544 public static String getFileContents(Path path) {
547 return new String(Files.readAllBytes(path));
549 } catch (Exception exception) {
550 LOGGER.error("Error while getting '{}' content", path.toString(), exception);
555 public static Object getDefaultFor(Class<?> clazz) {
556 if (byte.class == clazz) {
557 return new Byte("0");
558 } else if (short.class == clazz) {
559 return new Short("0");
560 } else if (int.class == clazz) {
561 return new Integer("0");
562 } else if (float.class == clazz) {
563 return new Float("0");
564 } else if (long.class == clazz) {
565 return new Long("0");
566 } else if (double.class == clazz) {
567 return new Double("0");
568 } else if (boolean.class == clazz) {
569 return Boolean.FALSE;
574 public static Collection getCompatibleCollectionForAbstractDef(Class<?> clazz) {
575 if (TransferQueue.class.isAssignableFrom(clazz)) {
576 return getConcreteCollection(TransferQueue.class);
578 if (BlockingQueue.class.isAssignableFrom(clazz)) {
579 return getConcreteCollection(BlockingQueue.class);
581 if (Deque.class.isAssignableFrom(clazz)) {
582 return getConcreteCollection(Deque.class);
584 if (Queue.class.isAssignableFrom(clazz)) {
585 return getConcreteCollection(Queue.class);
587 if (SortedSet.class.isAssignableFrom(clazz)) {
588 return getConcreteCollection(SortedSet.class);
590 if (Set.class.isAssignableFrom(clazz)) {
591 return getConcreteCollection(Set.class);
593 if (List.class.isAssignableFrom(clazz)) {
594 return getConcreteCollection(List.class);
596 throw new IllegalArgumentException("Only corresponding array classes and any are allowed as argument."
597 + "assignable from TransferQueue, BlockingQueue, Deque, Queue, SortedSet, Set, List class");
600 public static Collection getConcreteCollection(Class<?> clazz) {
601 switch (clazz.getName()) {
602 case "java.util.Collection":
603 case "java.util.List":
604 return new ArrayList<>();
605 case "java.util.Set":
606 return new HashSet<>();
607 case "java.util.SortedSet":
608 return new TreeSet<>();
609 case "java.util.Queue":
610 return new ConcurrentLinkedQueue<>();
611 case "java.util.Deque":
612 return new ArrayDeque<>();
613 case "java.util.concurrent.TransferQueue":
614 return new LinkedTransferQueue<>();
615 case "java.util.concurrent.BlockingQueue":
616 return new LinkedBlockingQueue<>();
618 throw new IllegalArgumentException("Only corresponding array classes and any are allowed as argument."
619 + "assignable from TransferQueue, BlockingQueue, Deque, Queue, SortedSet, Set, List class");
623 public static String getConfigurationRepositoryKey(File file) {
624 return getConfigurationRepositoryKey(
625 ConfigurationUtils.getNamespace(file).split(Constants.TENANT_NAMESPACE_SEPARATOR));
628 public static String getConfigurationRepositoryKey(URL url) {
629 return getConfigurationRepositoryKey(
630 ConfigurationUtils.getNamespace(url).split(Constants.TENANT_NAMESPACE_SEPARATOR));
633 public static String getConfigurationRepositoryKey(String[] array) {
634 Deque<String> stack = new ArrayDeque<>();
635 stack.push(Constants.DEFAULT_TENANT);
636 for (String element : array) {
639 String toReturn = stack.pop();
640 return stack.pop() + Constants.KEY_ELEMENTS_DELIMITER + toReturn;
643 public static String getNamespace(File file) {
644 Optional<String> namespace =
645 getConfiguration(file).flatMap(ConfigurationUtils::readNamespace).map(String::toUpperCase);
646 return namespace.orElseGet(() -> getNamespace(file.getName().toUpperCase()));
649 public static String getNamespace(String file) {
650 file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
651 file = file.substring(file.lastIndexOf('/') + 1);
652 Pattern pattern = Pattern.compile(
654 CONFIG_REGEX_TPL_OPT_1,
655 ConfigurationMode.OVERRIDE,
656 ConfigurationMode.MERGE,
657 ConfigurationMode.UNION,
658 ConfigurationType.PROPERTIES.name(),
659 ConfigurationType.XML.name(),
660 ConfigurationType.JSON.name(),
661 ConfigurationType.YAML.name()
664 Matcher matcher = pattern.matcher(file);
665 boolean b1 = matcher.matches();
667 if (matcher.group(1) != null) {
668 String moduleName = matcher.group(1).substring(1);
669 return moduleName.equalsIgnoreCase(ConfigurationMode.OVERRIDE.name()) || moduleName.equalsIgnoreCase(
670 ConfigurationMode.UNION.name()) || moduleName.equalsIgnoreCase(ConfigurationMode.MERGE.name())
671 ? Constants.DEFAULT_NAMESPACE : moduleName;
673 return Constants.DEFAULT_NAMESPACE;
675 } else if (isConfig(file)) {
676 return Constants.DEFAULT_NAMESPACE;
682 public static String getNamespace(URL url) {
684 Optional<String> namespace =
685 getConfiguration(url).flatMap(ConfigurationUtils::readNamespace).map(String::toUpperCase);
687 return namespace.orElseGet(() -> getNamespace(url.getFile().toUpperCase()));
690 public static Object getProperty(Configuration config, String key, int processingHints) {
691 if (!isDirectLookup(processingHints) && isNodeSpecific(processingHints) && (config instanceof CompositeConfiguration)) {
692 CompositeConfiguration conf = (CompositeConfiguration) config;
693 for (int i = 0; i < conf.getNumberOfConfigurations(); i++) {
694 Object obj = conf.getConfiguration(i).getProperty(key);
700 return config.getProperty(key);
703 public static boolean isCollection(String input) {
704 Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
705 Matcher matcher = pattern.matcher(input);
706 return matcher.matches();
709 public static boolean isDirectLookup(int hints) {
710 return (hints & LATEST_LOOKUP.value()) == LATEST_LOOKUP.value();
713 public static boolean isNodeSpecific(int hints) {
714 return (hints & NODE_SPECIFIC.value()) == NODE_SPECIFIC.value();
717 public static boolean isExternalLookup(int hints) {
718 return (hints & EXTERNAL_LOOKUP.value()) == EXTERNAL_LOOKUP.value();
721 public static boolean isZeroLengthArray(Class<?> clazz, Object obj) {
722 if (isAPrimitivesArray(clazz)) {
723 if (clazz.getComponentType() == int.class) {
724 return ((int[]) obj).length == 0;
725 } else if (clazz.getComponentType() == byte.class) {
726 return ((byte[]) obj).length == 0;
727 } else if (clazz.getComponentType() == short.class) {
728 return ((short[]) obj).length == 0;
729 } else if (clazz.getComponentType() == float.class) {
730 return ((float[]) obj).length == 0;
731 } else if (clazz.getComponentType() == boolean.class) {
732 return ((boolean[]) obj).length == 0;
733 } else if (clazz.getComponentType() == double.class) {
734 return ((double[]) obj).length == 0;
735 } else if (clazz.getComponentType() == long.class) {
736 return ((long[]) obj).length == 0;
738 return ((Object[]) obj).length == 0;
745 public static boolean isBlank(String value) {
746 return value == null || value.trim().isEmpty();
749 // private methods section starts here
751 private static int[] getIntsPrimitiveArray(Collection<?> collection) {
752 int collectionSize = collection.size();
753 int[] array = new int[collectionSize];
754 Object[] objArray = collection.toArray();
755 for (int i = 0; i < collectionSize; i++) {
756 array[i] = (int) objArray[i];
761 private static byte[] getBytesPrimitiveArray(Collection<?> collection) {
762 int collectionSize = collection.size();
763 byte[] array = new byte[collectionSize];
764 Object[] objArray = collection.toArray();
765 for (int i = 0; i < collectionSize; i++) {
766 array[i] = (byte) objArray[i];
771 private static short[] getShortsPrimitiveArray(Collection<?> collection) {
772 int collectionSize = collection.size();
773 short[] array = new short[collectionSize];
774 Object[] objArray = collection.toArray();
775 for (int i = 0; i < collectionSize; i++) {
776 array[i] = (short) objArray[i];
781 private static long[] getLongsPrimitiveArray(Collection<?> collection) {
782 int collectionSize = collection.size();
783 long[] array = new long[collectionSize];
784 Object[] objArray = collection.toArray();
785 for (int i = 0; i < collectionSize; i++) {
786 array[i] = (long) objArray[i];
791 private static float[] getFloatsPrimitiveArray(Collection<?> collection) {
792 int collectionSize = collection.size();
793 float[] array = new float[collectionSize];
794 Object[] objArray = collection.toArray();
795 for (int i = 0; i < collectionSize; i++) {
796 array[i] = (float) objArray[i];
801 private static double[] getDoublesPrimitiveArray(Collection<?> collection) {
802 int collectionSize = collection.size();
803 double[] array = new double[collectionSize];
804 Object[] objArray = collection.toArray();
805 for (int i = 0; i < collectionSize; i++) {
806 array[i] = (double) objArray[i];
811 private static boolean[] getBooleansPrimitiveArray(Collection<?> collection) {
812 int collectionSize = collection.size();
813 boolean[] array = new boolean[collectionSize];
814 Object[] objArray = collection.toArray();
815 for (int i = 0; i < collectionSize; i++) {
816 array[i] = (boolean) objArray[i];
821 private static char[] getCharsPrimitiveArray(Collection<?> collection) {
822 int collectionSize = collection.size();
823 char[] array = new char[collectionSize];
824 Object[] objArray = collection.toArray();
825 for (int i = 0; i < collectionSize; i++) {
826 array[i] = (char) objArray[i];