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
19 package org.onap.config;
21 import static java.util.Optional.ofNullable;
22 import static org.onap.config.api.Hint.EXTERNAL_LOOKUP;
23 import static org.onap.config.api.Hint.LATEST_LOOKUP;
24 import static org.onap.config.api.Hint.NODE_SPECIFIC;
26 import com.virtlink.commons.configuration2.jackson.JsonConfiguration;
27 import io.github.classgraph.ClassGraph;
28 import io.github.classgraph.ScanResult;
30 import java.io.IOException;
31 import java.lang.reflect.Array;
32 import java.lang.reflect.Field;
33 import java.lang.reflect.ParameterizedType;
34 import java.lang.reflect.Type;
35 import java.net.MalformedURLException;
37 import java.nio.charset.Charset;
38 import java.nio.file.FileVisitResult;
39 import java.nio.file.Files;
40 import java.nio.file.Path;
41 import java.nio.file.SimpleFileVisitor;
42 import java.nio.file.attribute.BasicFileAttributes;
43 import java.util.ArrayDeque;
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.Collection;
47 import java.util.Collections;
48 import java.util.Deque;
49 import java.util.HashMap;
50 import java.util.HashSet;
51 import java.util.List;
53 import java.util.Objects;
54 import java.util.Optional;
55 import java.util.Queue;
57 import java.util.SortedSet;
58 import java.util.TreeSet;
59 import java.util.concurrent.BlockingQueue;
60 import java.util.concurrent.ConcurrentLinkedQueue;
61 import java.util.concurrent.LinkedBlockingQueue;
62 import java.util.concurrent.LinkedTransferQueue;
63 import java.util.concurrent.TransferQueue;
64 import java.util.function.Predicate;
65 import java.util.regex.Matcher;
66 import java.util.regex.Pattern;
67 import java.util.stream.Collectors;
68 import org.apache.commons.configuration2.CompositeConfiguration;
69 import org.apache.commons.configuration2.Configuration;
70 import org.apache.commons.configuration2.FileBasedConfiguration;
71 import org.apache.commons.configuration2.PropertiesConfiguration;
72 import org.apache.commons.configuration2.XMLConfiguration;
73 import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
74 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
75 import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
76 import org.apache.commons.configuration2.builder.fluent.Configurations;
77 import org.apache.commons.configuration2.builder.fluent.Parameters;
78 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
79 import org.apache.commons.configuration2.ex.ConfigurationException;
80 import org.apache.commons.io.IOUtils;
81 import org.onap.config.api.Config;
82 import org.onap.config.api.ConfigurationManager;
83 import org.onap.config.impl.YamlConfiguration;
84 import org.onap.config.type.ConfigurationMode;
85 import org.onap.config.type.ConfigurationType;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
89 public class ConfigurationUtils {
91 private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationUtils.class);
92 private static final String CONFIGURATION_TYPE_NOT_SUPPORTED = "Configuration type not supported:";
93 private static final Map<Class<?>, Class<?>> ARRAY_CLASS_MAP;
94 private static final String CONFIG_REGEX_TPL_OPT_1 = "CONFIG(-\\w*){0,1}(-(%s|%s|%s)){0,1}\\.(%s|%s|%s|%s)$";
95 private static final String CONFIG_REGEX_TPL_OPT_2 = "CONFIG(.)*\\.(%s|%s|%s|%s)$";
98 Map<Class<?>, Class<?>> arrayTypes = new HashMap<>();
99 arrayTypes.put(Byte.class, Byte[].class);
100 arrayTypes.put(Short.class, Short[].class);
101 arrayTypes.put(Integer.class, Integer[].class);
102 arrayTypes.put(Long.class, Long[].class);
103 arrayTypes.put(Float.class, Float[].class);
104 arrayTypes.put(Double.class, Double[].class);
105 arrayTypes.put(Boolean.class, Boolean[].class);
106 arrayTypes.put(Character.class, Character[].class);
107 arrayTypes.put(String.class, String[].class);
108 ARRAY_CLASS_MAP = Collections.unmodifiableMap(arrayTypes);
111 private ConfigurationUtils() {
112 // prevent instantiation
115 public static Collection<File> getAllFiles(File file, boolean recursive, boolean onlyDirectory) {
116 ArrayList<File> collection = new ArrayList<>();
117 Path rootPath = file.toPath();
119 Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
121 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
122 super.preVisitDirectory(dir, attrs);
123 if (rootPath.equals(dir)) {
124 return FileVisitResult.CONTINUE;
126 collection.add(dir.toFile());
127 return recursive ? FileVisitResult.CONTINUE : FileVisitResult.SKIP_SUBTREE;
131 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
132 super.visitFile(file, attrs);
133 if (!onlyDirectory) {
134 collection.add(file.toFile());
136 return FileVisitResult.CONTINUE;
139 } catch (IOException e) {
140 LOGGER.error("Failed to walk through directories starting from: {}.", file.toString(), e);
145 public static String getCommaSeparatedList(String[] list) {
146 return (list == null) || (list.length == 0) ? "" : getCommaSeparatedList(Arrays.asList(list));
149 public static String getCommaSeparatedList(List<?> list) {
150 if ((list == null) || list.isEmpty()) {
153 return list.stream().filter(o -> o != null && !o.toString().trim().isEmpty()).map(o -> o.toString().trim()).collect(Collectors.joining(","));
156 public static boolean isConfig(URL url) {
157 return isConfig(url.getFile());
160 public static boolean isConfig(String file) {
161 file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
162 file = file.substring(file.lastIndexOf('/') + 1);
163 return file.matches(String.format(CONFIG_REGEX_TPL_OPT_1, ConfigurationMode.OVERRIDE, ConfigurationMode.MERGE, ConfigurationMode.UNION,
164 ConfigurationType.PROPERTIES.name(), ConfigurationType.XML.name(), ConfigurationType.JSON.name(), ConfigurationType.YAML.name())) || file
166 .format(CONFIG_REGEX_TPL_OPT_2, ConfigurationType.PROPERTIES.name(), ConfigurationType.XML.name(), ConfigurationType.JSON.name(),
167 ConfigurationType.YAML.name()));
170 public static boolean isConfig(File file) {
171 return file != null && file.exists() && isConfig(file.getName());
174 private static Optional<String> readNamespace(Configuration config) {
175 return ofNullable(config).flatMap(configuration -> ofNullable(configuration.getString(Constants.NAMESPACE_KEY))).map(String::toUpperCase);
178 private static Optional<String> readMergeStrategy(Configuration config) {
179 return ofNullable(config).flatMap(configuration -> ofNullable(configuration.getString(Constants.MODE_KEY))).map(String::toUpperCase);
182 public static ConfigurationMode getMergeStrategy(File file) {
183 Optional<ConfigurationMode> configurationMode = getConfiguration(file).flatMap(ConfigurationUtils::readMergeStrategy)
184 .flatMap(ConfigurationUtils::convertConfigurationMode);
185 return configurationMode.orElseGet(() -> getMergeStrategy(file.getName().toUpperCase()));
188 public static ConfigurationMode getMergeStrategy(URL url) {
189 Optional<ConfigurationMode> configurationMode = getConfiguration(url).flatMap(ConfigurationUtils::readMergeStrategy)
190 .flatMap(ConfigurationUtils::convertConfigurationMode);
191 return configurationMode.orElseGet(() -> getMergeStrategy(url.getFile().toUpperCase()));
194 public static ConfigurationMode getMergeStrategy(String file) {
195 file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
196 file = file.substring(file.lastIndexOf('/') + 1);
197 Pattern pattern = Pattern.compile(String
198 .format(CONFIG_REGEX_TPL_OPT_1, ConfigurationMode.OVERRIDE, ConfigurationMode.MERGE, ConfigurationMode.UNION,
199 ConfigurationType.PROPERTIES.name(), ConfigurationType.XML.name(), ConfigurationType.JSON.name(), ConfigurationType.YAML.name()));
200 Matcher matcher = pattern.matcher(file);
201 boolean b1 = matcher.matches();
203 for (int i = 1; i <= matcher.groupCount(); i++) {
204 String modeName = matcher.group(i);
205 if (modeName != null) {
206 modeName = modeName.substring(1);
209 return Enum.valueOf(ConfigurationMode.class, modeName);
210 } catch (Exception exception) {
211 LOGGER.debug("Configuration mode for merge strategy '{}' not found", modeName, exception);
218 public static Optional<FileBasedConfiguration> getConfiguration(URL url) {
220 ConfigurationType configType = ConfigurationUtils.getConfigType(url);
221 switch (configType) {
223 return Optional.of(new Configurations().fileBased(PropertiesConfiguration.class, url));
225 return Optional.of(new Configurations().fileBased(XMLConfiguration.class, url));
227 return Optional.of(new Configurations().fileBased(JsonConfiguration.class, url));
229 return Optional.of(new Configurations().fileBased(YamlConfiguration.class, url));
231 throw new ConfigurationException(CONFIGURATION_TYPE_NOT_SUPPORTED + configType);
233 } catch (ConfigurationException exception) {
234 LOGGER.error("Error reading configuration at {}.", url.toString(), exception);
236 return Optional.empty();
239 public static Optional<FileBasedConfiguration> getConfiguration(File file) {
241 return getConfiguration(file.getAbsoluteFile().toURI().toURL());
242 } catch (MalformedURLException e) {
243 throw new IllegalStateException("Malformed URL: " + file.getAbsolutePath());
247 public static ConfigurationType getConfigType(File file) {
248 Objects.requireNonNull(file, "File cannot be null");
249 return Enum.valueOf(ConfigurationType.class, file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf('.') + 1).toUpperCase());
252 public static ConfigurationType getConfigType(URL url) {
253 Objects.requireNonNull(url, "URL cannot be null");
254 return Enum.valueOf(ConfigurationType.class, url.getFile().substring(url.getFile().lastIndexOf('.') + 1).toUpperCase());
257 private static Optional<ConfigurationMode> convertConfigurationMode(String configMode) {
258 ConfigurationMode configurationMode = null;
260 configurationMode = ConfigurationMode.valueOf(configMode);
261 } catch (Exception exception) {
262 LOGGER.error("Could not find convert {} into configuration mode.", configMode, exception);
264 return Optional.ofNullable(configurationMode);
267 public static Class<?> getCollectionGenericType(Field field) {
268 Type type = field.getGenericType();
269 if (type instanceof ParameterizedType) {
270 ParameterizedType paramType = (ParameterizedType) type;
271 Type[] arr = paramType.getActualTypeArguments();
272 if (arr.length > 0) {
273 Class<?> clazz = (Class<?>) arr[0];
274 if (isWrapperClass(clazz)) {
277 throw new IllegalArgumentException("Collection of type " + clazz.getName() + " not supported.");
281 return String[].class;
284 public static boolean isWrapperClass(Class<?> clazz) {
285 Predicate<Class<?>> predicateWrapper = type -> type == String.class || type == Boolean.class || type == Character.class || Number.class
286 .isAssignableFrom(type);
287 return isA(predicateWrapper, clazz);
290 public static boolean isAPrimitive(Class<?> clazz) {
291 return isA(Class::isPrimitive, clazz);
295 * Check if clazz implementing Map iface
297 public static boolean isAMap(Class<?> clazz) {
298 Predicate<Class<?>> predicateMap = Map.class::isAssignableFrom;
299 return isA(predicateMap, clazz);
303 * Check if clazz implementing Collection iface
305 public static boolean isACollection(Class<?> clazz) {
306 Predicate<Class<?>> predicateCollection = Collection.class::isAssignableFrom;
307 return isA(predicateCollection, clazz);
311 * Check if clazz is a primitive or primitive wrapper
313 public static boolean isAPrimitiveOrWrapper(Class<?> clazz) {
314 Predicate<Class<?>> predicatePrimitive = Class::isPrimitive;
315 Predicate<Class<?>> predicateWrapper = ConfigurationUtils::isWrapperClass;
316 return isA(predicatePrimitive.or(predicateWrapper), clazz);
320 * Check if clazz is array of primitives or array of primitives wrappers
322 public static boolean isAPrimitivesOrWrappersArray(Class<?> clazz) {
323 Predicate<Class<?>> predicatePrimitivesOrWrappersArray = type -> ConfigurationUtils.isAWrappersArray(type) || ConfigurationUtils
324 .isAPrimitivesArray(type);
325 return isA(predicatePrimitivesOrWrappersArray, clazz);
329 * Check is clazz is array of primitives
331 public static boolean isAPrimitivesArray(Class<?> clazz) {
332 Predicate<Class<?>> predicateArray = Class::isArray;
333 Predicate<Class<?>> predicateComponentPrimitive = type -> type.getComponentType().isPrimitive();
334 return isA(predicateArray.and(predicateComponentPrimitive), clazz);
338 * Check is clazz is array of primitives wrappers
340 public static boolean isAWrappersArray(Class<?> clazz) {
341 Predicate<Class<?>> predicateArray = Class::isArray;
342 Predicate<Class<?>> predicateComponentWrapper = type -> isWrapperClass(type.getComponentType());
343 return isA(predicateArray.and(predicateComponentWrapper), clazz);
346 private static boolean isA(Predicate<Class<?>> predicate, Class<?> clazz) {
347 return predicate.test(clazz);
350 public static Class<?> getArrayClass(Class<?> clazz) {
351 return ARRAY_CLASS_MAP.getOrDefault(clazz, null);
354 public static List<URL> getAllClassPathResources() {
355 try (ScanResult scanResult = new ClassGraph().scan()) {
356 return scanResult.getAllResources().getURLs();
360 public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(File file) {
361 FileBasedConfigurationBuilder<FileBasedConfiguration> builder;
362 ConfigurationType configType = ConfigurationUtils.getConfigType(file);
363 builder = getFileBasedConfigurationBuilder(configType);
364 builder.configure(new Parameters().fileBased().setFile(file).setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
368 public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(URL url) {
369 ConfigurationType configType = ConfigurationUtils.getConfigType(url);
370 ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder = getFileBasedConfigurationBuilder(configType);
371 builder.configure(new Parameters().fileBased().setURL(url).setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
375 private static ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> getFileBasedConfigurationBuilder(ConfigurationType configType) {
376 ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder;
377 switch (configType) {
379 builder = new ReloadingFileBasedConfigurationBuilder<>(PropertiesConfiguration.class);
382 builder = new ReloadingFileBasedConfigurationBuilder<>(XMLConfiguration.class);
385 builder = new ReloadingFileBasedConfigurationBuilder<>(JsonConfiguration.class);
388 builder = new ReloadingFileBasedConfigurationBuilder<>(YamlConfiguration.class);
391 throw new IllegalArgumentException(CONFIGURATION_TYPE_NOT_SUPPORTED + configType);
396 public static <T> T read(Configuration config, Class<T> clazz, String keyPrefix) throws Exception {
397 Config confAnnotation = clazz.getAnnotation(Config.class);
398 if (confAnnotation != null) {
399 keyPrefix += (confAnnotation.key() + ".");
401 T objToReturn = clazz.newInstance();
402 for (Field field : clazz.getDeclaredFields()) {
403 Config fieldAnnotation = field.getAnnotation(Config.class);
404 if (fieldAnnotation != null) {
405 field.setAccessible(true);
406 field.set(objToReturn, config.getProperty(keyPrefix + fieldAnnotation.key()));
407 } else if (field.getType().getAnnotation(Config.class) != null) {
408 field.set(objToReturn, read(config, field.getType(), keyPrefix));
414 public static Object getPrimitiveArray(Collection<?> collection, Class<?> clazz) {
415 switch (clazz.getName()) {
417 return getIntsPrimitiveArray(collection);
419 return getBytesPrimitiveArray(collection);
421 return getShortsPrimitiveArray(collection);
423 return getLongsPrimitiveArray(collection);
425 return getFloatsPrimitiveArray(collection);
427 return getDoublesPrimitiveArray(collection);
429 return getBooleansPrimitiveArray(collection);
431 return getCharsPrimitiveArray(collection);
437 public static Object getWrappersArray(Collection<?> collection, Class<?> clazz) {
439 if (isWrapperClass(clazz)) {
440 int collectionSize = collection.size();
441 array = Array.newInstance(clazz, collection.size());
442 Object[] objArray = collection.toArray();
443 System.arraycopy(objArray, 0, array, 0, collectionSize);
448 public static String getCollectionString(String input) {
449 Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
450 Matcher matcher = pattern.matcher(input);
451 if (matcher.matches()) {
452 input = matcher.group(1);
457 public static String processVariablesIfPresent(String tenant, String namespace, String data) {
458 Pattern pattern = Pattern.compile("^.*\\$\\{(.*)\\}.*");
459 Matcher matcher = pattern.matcher(data);
460 if (matcher.matches()) {
461 final int substringStartIndex = 4;
462 String key = matcher.group(1);
464 if (key.toUpperCase().startsWith("ENV:")) {
465 value = System.getenv(key.substring(substringStartIndex));
466 } else if (key.toUpperCase().startsWith("SYS:")) {
467 value = System.getProperty(key.substring(substringStartIndex));
469 value = ConfigurationUtils.getCollectionString(ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key).toString());
471 return processVariablesIfPresent(tenant, namespace,
472 data.replaceAll("\\$\\{" + key + "}", value == null ? "" : value.replace("\\", "\\\\")));
478 public static String getFileContents(String path) {
481 return IOUtils.toString(new URL(path), Charset.defaultCharset());
483 } catch (Exception exception) {
484 LOGGER.error("Error while getting '{}' content", path, exception);
489 public static String getFileContents(Path path) {
492 return new String(Files.readAllBytes(path));
494 } catch (Exception exception) {
495 LOGGER.error("Error while getting '{}' content", path.toString(), exception);
500 public static Object getDefaultFor(Class<?> clazz) {
501 if (byte.class == clazz) {
502 return new Byte("0");
503 } else if (short.class == clazz) {
504 return new Short("0");
505 } else if (int.class == clazz) {
506 return new Integer("0");
507 } else if (float.class == clazz) {
508 return new Float("0");
509 } else if (long.class == clazz) {
510 return new Long("0");
511 } else if (double.class == clazz) {
512 return new Double("0");
513 } else if (boolean.class == clazz) {
514 return Boolean.FALSE;
519 public static Collection getCompatibleCollectionForAbstractDef(Class<?> clazz) {
520 if (TransferQueue.class.isAssignableFrom(clazz)) {
521 return getConcreteCollection(TransferQueue.class);
523 if (BlockingQueue.class.isAssignableFrom(clazz)) {
524 return getConcreteCollection(BlockingQueue.class);
526 if (Deque.class.isAssignableFrom(clazz)) {
527 return getConcreteCollection(Deque.class);
529 if (Queue.class.isAssignableFrom(clazz)) {
530 return getConcreteCollection(Queue.class);
532 if (SortedSet.class.isAssignableFrom(clazz)) {
533 return getConcreteCollection(SortedSet.class);
535 if (Set.class.isAssignableFrom(clazz)) {
536 return getConcreteCollection(Set.class);
538 if (List.class.isAssignableFrom(clazz)) {
539 return getConcreteCollection(List.class);
541 throw new IllegalArgumentException("Only corresponding array classes and any are allowed as argument."
542 + "assignable from TransferQueue, BlockingQueue, Deque, Queue, SortedSet, Set, List class");
545 public static Collection getConcreteCollection(Class<?> clazz) {
546 switch (clazz.getName()) {
547 case "java.util.Collection":
548 case "java.util.List":
549 return new ArrayList<>();
550 case "java.util.Set":
551 return new HashSet<>();
552 case "java.util.SortedSet":
553 return new TreeSet<>();
554 case "java.util.Queue":
555 return new ConcurrentLinkedQueue<>();
556 case "java.util.Deque":
557 return new ArrayDeque<>();
558 case "java.util.concurrent.TransferQueue":
559 return new LinkedTransferQueue<>();
560 case "java.util.concurrent.BlockingQueue":
561 return new LinkedBlockingQueue<>();
563 throw new IllegalArgumentException("Only corresponding array classes and any are allowed as argument."
564 + "assignable from TransferQueue, BlockingQueue, Deque, Queue, SortedSet, Set, List class");
568 public static String getConfigurationRepositoryKey(File file) {
569 return getConfigurationRepositoryKey(ConfigurationUtils.getNamespace(file).split(Constants.TENANT_NAMESPACE_SEPARATOR));
572 public static String getConfigurationRepositoryKey(URL url) {
573 return getConfigurationRepositoryKey(ConfigurationUtils.getNamespace(url).split(Constants.TENANT_NAMESPACE_SEPARATOR));
576 public static String getConfigurationRepositoryKey(String[] array) {
577 Deque<String> stack = new ArrayDeque<>();
578 stack.push(Constants.DEFAULT_TENANT);
579 for (String element : array) {
582 String toReturn = stack.pop();
583 return stack.pop() + Constants.KEY_ELEMENTS_DELIMITER + toReturn;
586 public static String getNamespace(File file) {
587 Optional<String> namespace = getConfiguration(file).flatMap(ConfigurationUtils::readNamespace).map(String::toUpperCase);
588 return namespace.orElseGet(() -> getNamespace(file.getName().toUpperCase()));
591 public static String getNamespace(String file) {
592 file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
593 file = file.substring(file.lastIndexOf('/') + 1);
594 Pattern pattern = Pattern.compile(String
595 .format(CONFIG_REGEX_TPL_OPT_1, ConfigurationMode.OVERRIDE, ConfigurationMode.MERGE, ConfigurationMode.UNION,
596 ConfigurationType.PROPERTIES.name(), ConfigurationType.XML.name(), ConfigurationType.JSON.name(), ConfigurationType.YAML.name()));
597 Matcher matcher = pattern.matcher(file);
598 boolean b1 = matcher.matches();
600 if (matcher.group(1) != null) {
601 String moduleName = matcher.group(1).substring(1);
602 return moduleName.equalsIgnoreCase(ConfigurationMode.OVERRIDE.name()) || moduleName.equalsIgnoreCase(ConfigurationMode.UNION.name())
603 || moduleName.equalsIgnoreCase(ConfigurationMode.MERGE.name()) ? Constants.DEFAULT_NAMESPACE : moduleName;
605 return Constants.DEFAULT_NAMESPACE;
607 } else if (isConfig(file)) {
608 return Constants.DEFAULT_NAMESPACE;
613 public static String getNamespace(URL url) {
614 Optional<String> namespace = getConfiguration(url).flatMap(ConfigurationUtils::readNamespace).map(String::toUpperCase);
615 return namespace.orElseGet(() -> getNamespace(url.getFile().toUpperCase()));
618 public static Object getProperty(Configuration config, String key, int processingHints) {
619 if (!isDirectLookup(processingHints) && isNodeSpecific(processingHints) && (config instanceof CompositeConfiguration)) {
620 CompositeConfiguration conf = (CompositeConfiguration) config;
621 for (int i = 0; i < conf.getNumberOfConfigurations(); i++) {
622 Object obj = conf.getConfiguration(i).getProperty(key);
628 return config.getProperty(key);
631 public static boolean isCollection(String input) {
632 Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
633 Matcher matcher = pattern.matcher(input);
634 return matcher.matches();
637 public static boolean isDirectLookup(int hints) {
638 return (hints & LATEST_LOOKUP.value()) == LATEST_LOOKUP.value();
641 public static boolean isNodeSpecific(int hints) {
642 return (hints & NODE_SPECIFIC.value()) == NODE_SPECIFIC.value();
645 public static boolean isExternalLookup(int hints) {
646 return (hints & EXTERNAL_LOOKUP.value()) == EXTERNAL_LOOKUP.value();
649 public static boolean isZeroLengthArray(Class<?> clazz, Object obj) {
650 if (isAPrimitivesArray(clazz)) {
651 if (clazz.getComponentType() == int.class) {
652 return ((int[]) obj).length == 0;
653 } else if (clazz.getComponentType() == byte.class) {
654 return ((byte[]) obj).length == 0;
655 } else if (clazz.getComponentType() == short.class) {
656 return ((short[]) obj).length == 0;
657 } else if (clazz.getComponentType() == float.class) {
658 return ((float[]) obj).length == 0;
659 } else if (clazz.getComponentType() == boolean.class) {
660 return ((boolean[]) obj).length == 0;
661 } else if (clazz.getComponentType() == double.class) {
662 return ((double[]) obj).length == 0;
663 } else if (clazz.getComponentType() == long.class) {
664 return ((long[]) obj).length == 0;
666 return ((Object[]) obj).length == 0;
672 public static boolean isBlank(String value) {
673 return value == null || value.trim().isEmpty();
676 // private methods section starts here
677 private static int[] getIntsPrimitiveArray(Collection<?> collection) {
678 int collectionSize = collection.size();
679 int[] array = new int[collectionSize];
680 Object[] objArray = collection.toArray();
681 for (int i = 0; i < collectionSize; i++) {
682 array[i] = (int) objArray[i];
687 private static byte[] getBytesPrimitiveArray(Collection<?> collection) {
688 int collectionSize = collection.size();
689 byte[] array = new byte[collectionSize];
690 Object[] objArray = collection.toArray();
691 for (int i = 0; i < collectionSize; i++) {
692 array[i] = (byte) objArray[i];
697 private static short[] getShortsPrimitiveArray(Collection<?> collection) {
698 int collectionSize = collection.size();
699 short[] array = new short[collectionSize];
700 Object[] objArray = collection.toArray();
701 for (int i = 0; i < collectionSize; i++) {
702 array[i] = (short) objArray[i];
707 private static long[] getLongsPrimitiveArray(Collection<?> collection) {
708 int collectionSize = collection.size();
709 long[] array = new long[collectionSize];
710 Object[] objArray = collection.toArray();
711 for (int i = 0; i < collectionSize; i++) {
712 array[i] = (long) objArray[i];
717 private static float[] getFloatsPrimitiveArray(Collection<?> collection) {
718 int collectionSize = collection.size();
719 float[] array = new float[collectionSize];
720 Object[] objArray = collection.toArray();
721 for (int i = 0; i < collectionSize; i++) {
722 array[i] = (float) objArray[i];
727 private static double[] getDoublesPrimitiveArray(Collection<?> collection) {
728 int collectionSize = collection.size();
729 double[] array = new double[collectionSize];
730 Object[] objArray = collection.toArray();
731 for (int i = 0; i < collectionSize; i++) {
732 array[i] = (double) objArray[i];
737 private static boolean[] getBooleansPrimitiveArray(Collection<?> collection) {
738 int collectionSize = collection.size();
739 boolean[] array = new boolean[collectionSize];
740 Object[] objArray = collection.toArray();
741 for (int i = 0; i < collectionSize; i++) {
742 array[i] = (boolean) objArray[i];
747 private static char[] getCharsPrimitiveArray(Collection<?> collection) {
748 int collectionSize = collection.size();
749 char[] array = new char[collectionSize];
750 Object[] objArray = collection.toArray();
751 for (int i = 0; i < collectionSize; i++) {
752 array[i] = (char) objArray[i];