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.
17 package org.onap.config;
19 import static java.util.Optional.ofNullable;
20 import static org.onap.config.api.Hint.EXTERNAL_LOOKUP;
21 import static org.onap.config.api.Hint.LATEST_LOOKUP;
22 import static org.onap.config.api.Hint.NODE_SPECIFIC;
24 import com.virtlink.commons.configuration2.jackson.JsonConfiguration;
26 import java.lang.reflect.Field;
27 import java.lang.reflect.ParameterizedType;
28 import java.lang.reflect.Type;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.util.ArrayDeque;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.Deque;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.Iterator;
41 import java.util.LinkedHashMap;
42 import java.util.List;
44 import java.util.Optional;
45 import java.util.Queue;
47 import java.util.SortedSet;
48 import java.util.TreeSet;
49 import java.util.concurrent.BlockingQueue;
50 import java.util.concurrent.ConcurrentLinkedQueue;
51 import java.util.concurrent.Executors;
52 import java.util.concurrent.LinkedBlockingQueue;
53 import java.util.concurrent.LinkedTransferQueue;
54 import java.util.concurrent.ThreadFactory;
55 import java.util.concurrent.TransferQueue;
56 import java.util.regex.Matcher;
57 import java.util.regex.Pattern;
58 import java.util.stream.Collectors;
59 import java.util.stream.Stream;
60 import net.sf.corn.cps.CPScanner;
61 import net.sf.corn.cps.ResourceFilter;
62 import org.apache.commons.configuration2.CompositeConfiguration;
63 import org.apache.commons.configuration2.Configuration;
64 import org.apache.commons.configuration2.FileBasedConfiguration;
65 import org.apache.commons.configuration2.PropertiesConfiguration;
66 import org.apache.commons.configuration2.XMLConfiguration;
67 import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
68 import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
69 import org.apache.commons.configuration2.builder.fluent.Configurations;
70 import org.apache.commons.configuration2.builder.fluent.Parameters;
71 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
72 import org.apache.commons.configuration2.ex.ConfigurationException;
73 import org.apache.commons.io.IOUtils;
74 import org.onap.config.api.Config;
75 import org.onap.config.api.ConfigurationManager;
76 import org.onap.config.impl.AgglomerateConfiguration;
77 import org.onap.config.impl.ConfigurationRepository;
78 import org.onap.config.impl.YamlConfiguration;
79 import org.onap.config.type.ConfigurationMode;
80 import org.onap.config.type.ConfigurationType;
81 import org.slf4j.Logger;
82 import org.slf4j.LoggerFactory;
84 public class ConfigurationUtils {
86 private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationUtils.class);
87 private static final String CONFIGURATION_TYPE_NOT_SUPPORTED = "Configuration type not supported:";
88 private static final Map<Class, Class> ARRAY_CLASS_MAP;
91 Map<Class, Class> arrayTypes = new HashMap<>();
92 arrayTypes.put(Byte.class, Byte[].class);
93 arrayTypes.put(Short.class, Short[].class);
94 arrayTypes.put(Integer.class, Integer[].class);
95 arrayTypes.put(Long.class, Long[].class);
96 arrayTypes.put(Float.class, Float[].class);
97 arrayTypes.put(Double.class, Double[].class);
98 arrayTypes.put(Boolean.class, Boolean[].class);
99 arrayTypes.put(Character.class, Character[].class);
100 arrayTypes.put(String.class, String[].class);
101 ARRAY_CLASS_MAP = Collections.unmodifiableMap(arrayTypes);
104 private ConfigurationUtils() {
107 public static ThreadFactory getThreadFactory() {
109 Thread thread = Executors.privilegedThreadFactory().newThread(r1);
110 thread.setDaemon(true);
115 public static Collection<File> getAllFiles(File file, boolean recursive, boolean onlyDirectory) {
116 ArrayList<File> collection = new ArrayList<>();
117 if (file.isDirectory() && file.exists()) {
118 File[] files = file.listFiles();
119 for (File innerFile : files) {
120 if (innerFile.isFile() && !onlyDirectory) {
121 collection.add(innerFile);
122 } else if (innerFile.isDirectory()) {
123 collection.add(innerFile);
125 collection.addAll(getAllFiles(innerFile, recursive, onlyDirectory));
133 public static String getCommaSeparatedList(String[] list) {
134 return getCommaSeparatedList(list == null ? Collections.emptyList() : Arrays.asList(list));
137 public static String getCommaSeparatedList(List list) {
138 return ((Stream<String>) list.stream().filter(o -> o != null && !o.toString().trim().isEmpty())
139 .map(o -> o.toString().trim())).collect(Collectors.joining(","));
142 public static boolean isConfig(URL url) {
143 return isConfig(url.getFile());
146 public static boolean isConfig(String file) {
147 file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
148 file = file.substring(file.lastIndexOf('/') + 1);
150 "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE + "|"
151 + ConfigurationMode.UNION + ")){0,1}" + "\\.(" + ConfigurationType.PROPERTIES.name() + "|"
152 + ConfigurationType.XML.name() + "|" + ConfigurationType.JSON.name() + "|"
153 + ConfigurationType.YAML.name() + ")$") || file.matches(
154 "CONFIG(.)*\\.(" + ConfigurationType.PROPERTIES.name() + "|" + ConfigurationType.XML.name() + "|"
155 + ConfigurationType.JSON.name() + "|" + ConfigurationType.YAML.name() + ")$");
158 public static boolean isConfig(File file) {
159 return file != null && file.exists() && isConfig(file.getName());
162 private static Optional<String> getNamespace(Configuration config) {
163 return ofNullable(config).flatMap(configuration -> ofNullable(configuration.getString(Constants.NAMESPACE_KEY)))
164 .map(String::toUpperCase);
167 public static ConfigurationMode getMergeStrategy(URL url) {
168 Optional<ConfigurationMode> configurationMode =
169 getConfiguration(url).flatMap(ConfigurationUtils::getMergeStrategy)
170 .flatMap(ConfigurationUtils::convertConfigurationMode);
171 return configurationMode.orElseGet(() -> getMergeStrategy(url.getFile().toUpperCase()));
174 public static Optional<FileBasedConfiguration> getConfiguration(URL url) {
175 FileBasedConfiguration builder = null;
177 ConfigurationType configType = ConfigurationUtils.getConfigType(url);
178 switch (configType) {
180 builder = new Configurations().fileBased(PropertiesConfiguration.class, url);
183 builder = new Configurations().fileBased(XMLConfiguration.class, url);
186 builder = new Configurations().fileBased(JsonConfiguration.class, url);
189 builder = new Configurations().fileBased(YamlConfiguration.class, url);
192 throw new ConfigurationException(CONFIGURATION_TYPE_NOT_SUPPORTED + configType);
194 } catch (ConfigurationException exception) {
195 exception.printStackTrace();
197 return ofNullable(builder);
200 public static ConfigurationMode getMergeStrategy(String file) {
201 file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
202 file = file.substring(file.lastIndexOf('/') + 1);
203 Pattern pattern = Pattern.compile(
204 "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE + "|"
205 + ConfigurationMode.UNION + ")){0,1}" + "\\.(" + ConfigurationType.PROPERTIES.name() + "|"
206 + ConfigurationType.XML.name() + "|" + ConfigurationType.JSON.name() + "|"
207 + ConfigurationType.YAML.name() + ")$");
208 Matcher matcher = pattern.matcher(file);
209 boolean b1 = matcher.matches();
211 for (int i = 1; i <= matcher.groupCount(); i++) {
212 String modeName = matcher.group(i);
213 if (modeName != null) {
214 modeName = modeName.substring(1);
217 return Enum.valueOf(ConfigurationMode.class, modeName);
218 } catch (Exception exception) {
227 public static ConfigurationType getConfigType(URL url) {
228 return Enum.valueOf(ConfigurationType.class,
229 url.getFile().substring(url.getFile().lastIndexOf('.') + 1).toUpperCase());
232 private static Optional<ConfigurationMode> convertConfigurationMode(String configMode) {
233 ConfigurationMode configurationMode = null;
235 configurationMode = ConfigurationMode.valueOf(configMode);
236 } catch (Exception exception) {
237 LOGGER.error("Could not find convert {} into configuration mode", configMode);
239 return Optional.ofNullable(configurationMode);
242 private static Optional<String> getMergeStrategy(Configuration config) {
243 return ofNullable(config).flatMap(configuration -> ofNullable(configuration.getString(Constants.MODE_KEY)))
244 .map(String::toUpperCase);
247 public static ConfigurationMode getMergeStrategy(File file) {
248 Optional<ConfigurationMode> configurationMode =
249 getConfiguration(file).flatMap(ConfigurationUtils::getMergeStrategy)
250 .flatMap(ConfigurationUtils::convertConfigurationMode);
251 return configurationMode.orElseGet(() -> getMergeStrategy(file.getName().toUpperCase()));
254 public static Optional<FileBasedConfiguration> getConfiguration(File file) {
255 FileBasedConfiguration builder = null;
257 ConfigurationType configType = ConfigurationUtils.getConfigType(file);
258 switch (configType) {
260 builder = new Configurations().fileBased(PropertiesConfiguration.class, file);
263 builder = new Configurations().fileBased(XMLConfiguration.class, file);
266 builder = new Configurations().fileBased(JsonConfiguration.class, file);
269 builder = new Configurations().fileBased(YamlConfiguration.class, file);
272 throw new ConfigurationException(CONFIGURATION_TYPE_NOT_SUPPORTED + configType);
274 } catch (ConfigurationException exception) {
275 exception.printStackTrace();
277 return ofNullable(builder);
280 public static ConfigurationType getConfigType(File file) {
281 return Enum.valueOf(ConfigurationType.class,
282 file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf('.') + 1).toUpperCase());
285 public static Class getCollectionGenericType(Field field) {
286 Type type = field.getGenericType();
288 if (type instanceof ParameterizedType) {
290 ParameterizedType paramType = (ParameterizedType) type;
291 Type[] arr = paramType.getActualTypeArguments();
292 if (arr.length > 0) {
293 Class<?> clazz = (Class<?>) arr[0];
294 if (isWrapperClass(clazz)) {
297 throw new RuntimeException("Collection of type " + clazz.getName() + " not supported.");
302 return String[].class;
305 public static boolean isWrapperClass(Class clazz) {
306 return clazz == String.class || clazz == Boolean.class || clazz == Character.class
307 || Number.class.isAssignableFrom(clazz);
310 public static Class getArrayClass(Class clazz) {
311 return ARRAY_CLASS_MAP.getOrDefault(clazz, null);
314 public static List<URL> getAllClassPathResources() {
315 return CPScanner.scanResources(new ResourceFilter());
318 public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(URL url) {
319 ConfigurationType configType = ConfigurationUtils.getConfigType(url);
320 ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder =
321 getFileBasedConfigurationReloadingFileBasedConfigurationBuilder(configType);
323 new Parameters().fileBased().setURL(url).setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
327 private static ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>
328 getFileBasedConfigurationReloadingFileBasedConfigurationBuilder(ConfigurationType configType) {
330 ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder;
331 switch (configType) {
333 builder = new ReloadingFileBasedConfigurationBuilder<>(PropertiesConfiguration.class);
336 builder = new ReloadingFileBasedConfigurationBuilder<>(XMLConfiguration.class);
339 builder = new ReloadingFileBasedConfigurationBuilder<>(JsonConfiguration.class);
342 builder = new ReloadingFileBasedConfigurationBuilder<>(YamlConfiguration.class);
345 throw new IllegalArgumentException(CONFIGURATION_TYPE_NOT_SUPPORTED + configType);
350 public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(File file,
352 ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder;
353 ConfigurationType configType = ConfigurationUtils.getConfigType(file);
354 builder = getFileBasedConfigurationReloadingFileBasedConfigurationBuilder(configType);
355 builder.configure(new Parameters().fileBased().setFile(file)
356 .setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
357 builder.setAutoSave(autoSave);
361 public static <T> T read(Configuration config, Class<T> clazz, String keyPrefix) throws Exception {
362 Config confAnnotation = clazz.getAnnotation(Config.class);
363 if (confAnnotation != null) {
364 keyPrefix += (confAnnotation.key() + ".");
366 T objToReturn = clazz.newInstance();
367 for (Field field : clazz.getDeclaredFields()) {
368 Config fieldAnnotation = field.getAnnotation(Config.class);
369 if (fieldAnnotation != null) {
370 field.setAccessible(true);
371 field.set(objToReturn, config.getProperty(keyPrefix + fieldAnnotation.key()));
372 } else if (field.getType().getAnnotation(Config.class) != null) {
373 field.set(objToReturn, read(config, field.getType(), keyPrefix));
379 public static Object getPrimitiveArray(Collection collection, Class clazz) {
380 if (clazz == int.class) {
381 int[] array = new int[collection.size()];
382 Object[] objArray = collection.toArray();
383 for (int i = 0; i < collection.size(); i++) {
384 array[i] = (int) objArray[i];
388 if (clazz == byte.class) {
389 byte[] array = new byte[collection.size()];
390 Object[] objArray = collection.toArray();
391 for (int i = 0; i < collection.size(); i++) {
392 array[i] = (byte) objArray[i];
396 if (clazz == short.class) {
397 short[] array = new short[collection.size()];
398 Object[] objArray = collection.toArray();
399 for (int i = 0; i < collection.size(); i++) {
400 array[i] = (short) objArray[i];
404 if (clazz == long.class) {
405 long[] array = new long[collection.size()];
406 Object[] objArray = collection.toArray();
407 for (int i = 0; i < collection.size(); i++) {
408 array[i] = (long) objArray[i];
412 if (clazz == float.class) {
413 float[] array = new float[collection.size()];
414 Object[] objArray = collection.toArray();
415 for (int i = 0; i < collection.size(); i++) {
416 array[i] = (float) objArray[i];
420 if (clazz == double.class) {
421 double[] array = new double[collection.size()];
422 Object[] objArray = collection.toArray();
423 for (int i = 0; i < collection.size(); i++) {
424 array[i] = (double) objArray[i];
428 if (clazz == boolean.class) {
429 boolean[] array = new boolean[collection.size()];
430 Object[] objArray = collection.toArray();
431 for (int i = 0; i < collection.size(); i++) {
432 array[i] = (boolean) objArray[i];
439 public static String getCollectionString(String input) {
440 Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
441 Matcher matcher = pattern.matcher(input);
442 if (matcher.matches()) {
443 input = matcher.group(1);
448 public static String processVariablesIfPresent(String tenant, String namespace, String data) {
449 Pattern pattern = Pattern.compile("^.*\\$\\{(.*)\\}.*");
450 Matcher matcher = pattern.matcher(data);
451 if (matcher.matches()) {
452 String key = matcher.group(1);
453 if (key.toUpperCase().startsWith("ENV:")) {
454 String envValue = System.getenv(key.substring(4));
455 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
456 envValue == null ? "" : envValue.replace("\\", "\\\\")));
457 } else if (key.toUpperCase().startsWith("SYS:")) {
458 String sysValue = System.getProperty(key.substring(4));
459 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
460 sysValue == null ? "" : sysValue.replace("\\", "\\\\")));
462 String propertyValue = ConfigurationUtils.getCollectionString(
463 ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key).toString());
464 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
465 propertyValue == null ? "" : propertyValue.replace("\\", "\\\\")));
472 public static String getFileContents(String path) {
475 return IOUtils.toString(new URL(path));
477 } catch (Exception exception) {
478 exception.printStackTrace();
483 public static String getFileContents(Path path) {
486 return new String(Files.readAllBytes(path));
488 } catch (Exception exception) {
489 exception.printStackTrace();
494 public static Object getDefaultFor(Class clazz) {
495 if (byte.class == clazz) {
496 return new Byte("0");
497 } else if (short.class == clazz) {
498 return new Short("0");
499 } else if (int.class == clazz) {
500 return new Integer("0");
501 } else if (float.class == clazz) {
502 return new Float("0");
503 } else if (long.class == clazz) {
504 return new Long("0");
505 } else if (double.class == clazz) {
506 return new Double("0");
507 } else if (boolean.class == clazz) {
508 return Boolean.FALSE;
513 public static Collection getCompatibleCollectionForAbstractDef(Class clazz) {
514 if (BlockingQueue.class.isAssignableFrom(clazz)) {
515 return getConcreteCollection(BlockingQueue.class);
517 if (TransferQueue.class.isAssignableFrom(clazz)) {
518 return getConcreteCollection(TransferQueue.class);
520 if (Deque.class.isAssignableFrom(clazz)) {
521 return getConcreteCollection(Deque.class);
523 if (Queue.class.isAssignableFrom(clazz)) {
524 return getConcreteCollection(Queue.class);
526 if (SortedSet.class.isAssignableFrom(clazz)) {
527 return getConcreteCollection(SortedSet.class);
529 if (Set.class.isAssignableFrom(clazz)) {
530 return getConcreteCollection(Set.class);
532 if (List.class.isAssignableFrom(clazz)) {
533 return getConcreteCollection(List.class);
538 public static Collection getConcreteCollection(Class clazz) {
539 switch (clazz.getName()) {
540 case "java.util.Collection":
541 case "java.util.List":
542 return new ArrayList<>();
543 case "java.util.Set":
544 return new HashSet<>();
545 case "java.util.SortedSet":
546 return new TreeSet<>();
547 case "java.util.Queue":
548 return new ConcurrentLinkedQueue<>();
549 case "java.util.Deque":
550 return new ArrayDeque<>();
551 case "java.util.concurrent.TransferQueue":
552 return new LinkedTransferQueue<>();
553 case "java.util.concurrent.BlockingQueue":
554 return new LinkedBlockingQueue<>();
560 public static String getConfigurationRepositoryKey(File file) {
561 return getConfigurationRepositoryKey(
562 ConfigurationUtils.getNamespace(file).split(Constants.TENANT_NAMESPACE_SEPARATOR));
565 public static String getConfigurationRepositoryKey(String[] array) {
566 Deque<String> stack = new ArrayDeque<>();
567 stack.push(Constants.DEFAULT_TENANT);
568 for (String element : array) {
571 String toReturn = stack.pop();
572 return stack.pop() + Constants.KEY_ELEMENTS_DELIMETER + toReturn;
575 public static String getNamespace(File file) {
576 Optional<String> namespace =
577 getConfiguration(file).flatMap(ConfigurationUtils::getNamespace).map(String::toUpperCase);
578 return namespace.orElseGet(() -> getNamespace(file.getName().toUpperCase()));
581 public static String getNamespace(String file) {
582 file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
583 file = file.substring(file.lastIndexOf('/') + 1);
584 Pattern pattern = Pattern.compile(
585 "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE + "|"
586 + ConfigurationMode.UNION + ")){0,1}" + "\\.(" + ConfigurationType.PROPERTIES.name() + "|"
587 + ConfigurationType.XML.name() + "|" + ConfigurationType.JSON.name() + "|"
588 + ConfigurationType.YAML.name() + ")$");
589 Matcher matcher = pattern.matcher(file);
590 boolean b1 = matcher.matches();
592 if (matcher.group(1) != null) {
593 String moduleName = matcher.group(1).substring(1);
594 return moduleName.equalsIgnoreCase(ConfigurationMode.OVERRIDE.name()) || moduleName.equalsIgnoreCase(
595 ConfigurationMode.UNION.name()) || moduleName.equalsIgnoreCase(ConfigurationMode.MERGE.name())
596 ? Constants.DEFAULT_NAMESPACE : moduleName;
598 return Constants.DEFAULT_NAMESPACE;
600 } else if (isConfig(file)) {
601 return Constants.DEFAULT_NAMESPACE;
607 public static String getConfigurationRepositoryKey(URL url) {
608 return getConfigurationRepositoryKey(
609 ConfigurationUtils.getNamespace(url).split(Constants.TENANT_NAMESPACE_SEPARATOR));
612 public static String getNamespace(URL url) {
614 Optional<String> namespace =
615 getConfiguration(url).flatMap(ConfigurationUtils::getNamespace).map(String::toUpperCase);
617 return namespace.orElseGet(() -> getNamespace(url.getFile().toUpperCase()));
620 public static LinkedHashMap toMap(Configuration config) {
621 Iterator<String> iterator = config.getKeys();
622 LinkedHashMap<String, String> map = new LinkedHashMap<>();
623 while (iterator.hasNext()) {
624 String key = iterator.next();
625 if (!(key.equals(Constants.MODE_KEY) || key.equals(Constants.NAMESPACE_KEY) || key.equals(
626 Constants.LOAD_ORDER_KEY))) {
627 map.put(key, config.getProperty(key).toString());
634 public static Map diff(LinkedHashMap orig, LinkedHashMap latest) {
635 orig = new LinkedHashMap<>(orig);
636 latest = new LinkedHashMap<>(latest);
637 List<String> set = new ArrayList(orig.keySet());
638 for (String key : set) {
639 if (latest.remove(key, orig.get(key))) {
643 Set<String> keys = latest.keySet();
644 for (String key : keys) {
647 set = new ArrayList(orig.keySet());
648 for (String key : set) {
651 return new HashMap<>(latest);
654 public static boolean isArray(String tenant, String namespace, String key, int processingHints) throws Exception {
655 Object obj = ConfigurationUtils
656 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace), key,
658 return (obj != null) && ConfigurationUtils.isCollection(obj.toString());
661 public static Object getProperty(Configuration config, String key, int processingHints) {
662 if (!isDirectLookup(processingHints)) {
663 if (config instanceof AgglomerateConfiguration) {
664 return ((AgglomerateConfiguration) config).getPropertyValue(key);
665 } else if (config instanceof CompositeConfiguration) {
666 CompositeConfiguration conf = (CompositeConfiguration) config;
667 for (int i = 0; i < conf.getNumberOfConfigurations(); i++) {
668 if (conf.getConfiguration(i) instanceof AgglomerateConfiguration) {
669 return ((AgglomerateConfiguration) conf.getConfiguration(i)).getPropertyValue(key);
670 } else if (isNodeSpecific(processingHints)) {
671 Object obj = conf.getConfiguration(i).getProperty(key);
679 return config.getProperty(key);
682 public static boolean isCollection(String input) {
683 Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
684 Matcher matcher = pattern.matcher(input);
685 return matcher.matches();
688 public static boolean isDirectLookup(int hints) {
689 return (hints & LATEST_LOOKUP.value()) == LATEST_LOOKUP.value();
692 public static boolean isNodeSpecific(int hints) {
693 return (hints & NODE_SPECIFIC.value()) == NODE_SPECIFIC.value();
696 public static boolean isExternalLookup(int hints) {
697 return (hints & EXTERNAL_LOOKUP.value()) == EXTERNAL_LOOKUP.value();
700 public static boolean isZeroLengthArray(Class clazz, Object obj) {
701 if (clazz.isArray() && clazz.getComponentType().isPrimitive()) {
702 if (clazz.getComponentType() == int.class) {
703 return ((int[]) obj).length == 0;
704 } else if (clazz.getComponentType() == byte.class) {
705 return ((byte[]) obj).length == 0;
706 } else if (clazz.getComponentType() == short.class) {
707 return ((short[]) obj).length == 0;
708 } else if (clazz.getComponentType() == float.class) {
709 return ((float[]) obj).length == 0;
710 } else if (clazz.getComponentType() == boolean.class) {
711 return ((boolean[]) obj).length == 0;
712 } else if (clazz.getComponentType() == double.class) {
713 return ((double[]) obj).length == 0;
714 } else if (clazz.getComponentType() == long.class) {
715 return ((long[]) obj).length == 0;
717 return ((Object[]) obj).length == 0;
724 public static boolean isBlank(String value) {
725 return value == null || value.trim().length() == 0;