424b5626d2bbc0f770c78fa989fa99659a4144e0
[sdc.git] /
1 package org.openecomp.config;
2
3 import com.virtlink.commons.configuration2.jackson.JsonConfiguration;
4 import net.sf.corn.cps.CPScanner;
5 import net.sf.corn.cps.ResourceFilter;
6 import org.apache.commons.configuration2.CompositeConfiguration;
7 import org.apache.commons.configuration2.Configuration;
8 import org.apache.commons.configuration2.FileBasedConfiguration;
9 import org.apache.commons.configuration2.PropertiesConfiguration;
10 import org.apache.commons.configuration2.XMLConfiguration;
11 import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
12 import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
13 import org.apache.commons.configuration2.builder.fluent.Configurations;
14 import org.apache.commons.configuration2.builder.fluent.Parameters;
15 import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
16 import org.apache.commons.configuration2.ex.ConfigurationException;
17 import org.apache.commons.io.IOUtils;
18 import org.openecomp.config.api.ConfigurationManager;
19 import org.openecomp.config.impl.AgglomerateConfiguration;
20 import org.openecomp.config.impl.ConfigurationDataSource;
21 import org.openecomp.config.impl.ConfigurationRepository;
22 import org.openecomp.config.impl.YamlConfiguration;
23 import org.openecomp.config.type.ConfigurationMode;
24 import org.openecomp.config.type.ConfigurationType;
25
26 import javax.sql.DataSource;
27 import java.io.File;
28 import java.lang.reflect.Field;
29 import java.lang.reflect.ParameterizedType;
30 import java.lang.reflect.Type;
31 import java.net.URL;
32 import java.nio.file.Files;
33 import java.nio.file.Path;
34 import java.sql.Connection;
35 import java.sql.PreparedStatement;
36 import java.sql.ResultSet;
37 import java.sql.Statement;
38 import java.util.ArrayDeque;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.Collection;
42 import java.util.Deque;
43 import java.util.HashMap;
44 import java.util.HashSet;
45 import java.util.Iterator;
46 import java.util.LinkedHashMap;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.Queue;
50 import java.util.Set;
51 import java.util.SortedSet;
52 import java.util.Stack;
53 import java.util.TreeSet;
54 import java.util.concurrent.BlockingQueue;
55 import java.util.concurrent.ConcurrentLinkedQueue;
56 import java.util.concurrent.Executors;
57 import java.util.concurrent.LinkedBlockingQueue;
58 import java.util.concurrent.LinkedTransferQueue;
59 import java.util.concurrent.ThreadFactory;
60 import java.util.concurrent.TransferQueue;
61 import java.util.regex.Matcher;
62 import java.util.regex.Pattern;
63 import java.util.stream.Collectors;
64 import java.util.stream.Stream;
65
66 import static org.openecomp.config.api.Hint.EXTERNAL_LOOKUP;
67 import static org.openecomp.config.api.Hint.LATEST_LOOKUP;
68 import static org.openecomp.config.api.Hint.NODE_SPECIFIC;
69
70 /**
71  * The type Configuration utils.
72  */
73 public class ConfigurationUtils {
74
75     private ConfigurationUtils() {
76     }
77
78
79     /**
80      * Gets thread factory.
81      *
82      * @return the thread factory
83      */
84     public static ThreadFactory getThreadFactory() {
85         return (r1) -> {
86             Thread thread = Executors.privilegedThreadFactory().newThread(r1);
87             thread.setDaemon(true);
88             return thread;
89         };
90     }
91
92     /**
93      * Gets all files.
94      *
95      * @param file          the file
96      * @param recursive     the recursive
97      * @param onlyDirectory the only directory
98      * @return the all files
99      */
100     public static Collection<File> getAllFiles(File file, boolean recursive, boolean onlyDirectory) {
101         ArrayList<File> collection = new ArrayList<>();
102         if (file.isDirectory() && file.exists()) {
103             File[] files = file.listFiles();
104             for (File innerFile : files) {
105                 if (innerFile.isFile() && !onlyDirectory) {
106                     collection.add(innerFile);
107                 } else if (innerFile.isDirectory()) {
108                     collection.add(innerFile);
109                     if (recursive) {
110                         collection.addAll(getAllFiles(innerFile, recursive, onlyDirectory));
111                     }
112                 }
113             }
114         }
115         return collection;
116     }
117
118     /**
119      * Gets comma saperated list.
120      *
121      * @param list the list
122      * @return the comma saperated list
123      */
124     public static String getCommaSeparatedList(List list) {
125         return ((Stream<String>) list.stream().filter(o -> o != null && !o.toString().trim().isEmpty()).map(o -> o.toString().trim())).collect(Collectors.joining(","));
126     }
127
128     /**
129      * Gets comma saperated list.
130      *
131      * @param list the list
132      * @return the comma saperated list
133      */
134     public static String getCommaSeparatedList(String[] list) {
135         return getCommaSeparatedList(list == null ? Arrays.asList() : Arrays.asList(list));
136     }
137
138     /**
139      * Gets config type.
140      *
141      * @param url the url
142      * @return the config type
143      */
144     public static ConfigurationType getConfigType(URL url) {
145         return Enum.valueOf(ConfigurationType.class,
146                 url.getFile().substring(url.getFile().lastIndexOf('.') + 1).toUpperCase());
147     }
148
149     /**
150      * Gets config type.
151      *
152      * @param file the file
153      * @return the config type
154      */
155     public static ConfigurationType getConfigType(File file) {
156         return Enum.valueOf(ConfigurationType.class,
157                 file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf('.') + 1)
158                         .toUpperCase());
159     }
160
161     /**
162      * Is config boolean.
163      *
164      * @param url the url
165      * @return the boolean
166      */
167     public static boolean isConfig(URL url) {
168         return isConfig(url.getFile());
169     }
170
171     /**
172      * Is config boolean.
173      *
174      * @param file the file
175      * @return the boolean
176      */
177     public static boolean isConfig(File file) {
178         return file != null && file.exists() && isConfig(file.getName());
179     }
180
181     /**
182      * Is config boolean.
183      *
184      * @param file the file
185      * @return the boolean
186      */
187     public static boolean isConfig(String file) {
188         file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
189         file = file.substring(file.lastIndexOf('/') + 1);
190         return file.matches(
191                 "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE
192                         + "|" + ConfigurationMode.UNION + ")){0,1}" + "\\.("
193                         + ConfigurationType.PROPERTIES.name() + "|" + ConfigurationType.XML.name() + "|"
194                         + ConfigurationType.JSON.name() + "|" + ConfigurationType.YAML.name() + ")$")
195                 || file.matches("CONFIG(.)*\\.(" + ConfigurationType.PROPERTIES.name() + "|"
196                 + ConfigurationType.XML.name() + "|" + ConfigurationType.JSON.name() + "|"
197                 + ConfigurationType.YAML.name() + ")$");
198     }
199
200     /**
201      * Gets namespace.
202      *
203      * @param url the url
204      * @return the namespace
205      */
206     public static String getNamespace(URL url) {
207         String namespace = getNamespace(getConfiguration(url));
208         if (namespace != null) {
209             return namespace.toUpperCase();
210         }
211         return getNamespace(url.getFile().toUpperCase());
212     }
213
214     /**
215      * Gets namespace.
216      *
217      * @param file the file
218      * @return the namespace
219      */
220     public static String getNamespace(File file) {
221         String namespace = getNamespace(getConfiguration(file));
222         if (namespace != null) {
223             return namespace.toUpperCase();
224         }
225         return getNamespace(file.getName().toUpperCase());
226     }
227
228     private static String getNamespace(Configuration config) {
229         return config.getString(Constants.NAMESPACE_KEY) == null ? null
230                 : config.getString(Constants.NAMESPACE_KEY).toUpperCase();
231     }
232
233     /**
234      * Gets namespace.
235      *
236      * @param file the file
237      * @return the namespace
238      */
239     public static String getNamespace(String file) {
240         file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
241         file = file.substring(file.lastIndexOf('/') + 1);
242         Pattern pattern = Pattern.compile(
243                 "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE
244                         + "|" + ConfigurationMode.UNION + ")){0,1}" + "\\.("
245                         + ConfigurationType.PROPERTIES.name() + "|" + ConfigurationType.XML.name() + "|"
246                         + ConfigurationType.JSON.name() + "|" + ConfigurationType.YAML.name() + ")$");
247         Matcher matcher = pattern.matcher(file);
248         boolean b1 = matcher.matches();
249         if (b1) {
250             if (matcher.group(1) != null) {
251                 String moduleName = matcher.group(1).substring(1);
252                 return moduleName.equalsIgnoreCase(ConfigurationMode.OVERRIDE.name())
253                         || moduleName.equalsIgnoreCase(ConfigurationMode.UNION.name())
254                         || moduleName.equalsIgnoreCase(ConfigurationMode.MERGE.name())
255                         ? Constants.DEFAULT_NAMESPACE : moduleName;
256             } else {
257                 return Constants.DEFAULT_NAMESPACE;
258             }
259         } else if (isConfig(file)) {
260             return Constants.DEFAULT_NAMESPACE;
261         }
262
263         return null;
264     }
265
266     /**
267      * Gets merge strategy.
268      *
269      * @param url the url
270      * @return the merge strategy
271      */
272     public static ConfigurationMode getMergeStrategy(URL url) {
273         String configMode = getMergeStrategy(getConfiguration(url));
274         if (configMode != null) {
275             try {
276                 return Enum.valueOf(ConfigurationMode.class, configMode);
277             } catch (Exception exception) {
278                 //do nothing
279             }
280         }
281         return getMergeStrategy(url.getFile().toUpperCase());
282     }
283
284     private static String getMergeStrategy(Configuration config) {
285         return config.getString(Constants.MODE_KEY) == null ? null
286                 : config.getString(Constants.MODE_KEY).toUpperCase();
287     }
288
289     /**
290      * Gets merge strategy.
291      *
292      * @param file the file
293      * @return the merge strategy
294      */
295     public static ConfigurationMode getMergeStrategy(File file) {
296         String configMode = getMergeStrategy(getConfiguration(file));
297         if (configMode != null) {
298             try {
299                 return Enum.valueOf(ConfigurationMode.class, configMode);
300             } catch (Exception exception) {
301                 //do nothing
302             }
303         }
304         return getMergeStrategy(file.getName().toUpperCase());
305     }
306
307     /**
308      * Gets merge strategy.
309      *
310      * @param file the file
311      * @return the merge strategy
312      */
313     public static ConfigurationMode getMergeStrategy(String file) {
314         file = file.toUpperCase().substring(file.lastIndexOf('!') + 1);
315         file = file.substring(file.lastIndexOf('/') + 1);
316         Pattern pattern = Pattern.compile(
317                 "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE
318                         + "|" + ConfigurationMode.UNION + ")){0,1}" + "\\.("
319                         + ConfigurationType.PROPERTIES.name() + "|" + ConfigurationType.XML.name() + "|"
320                         + ConfigurationType.JSON.name() + "|" + ConfigurationType.YAML.name() + ")$");
321         Matcher matcher = pattern.matcher(file);
322         boolean b1 = matcher.matches();
323         if (b1) {
324             for (int i = 1; i <= matcher.groupCount(); i++) {
325                 String modeName = matcher.group(i);
326                 if (modeName != null) {
327                     modeName = modeName.substring(1);
328                 }
329                 try {
330                     return Enum.valueOf(ConfigurationMode.class, modeName);
331                 } catch (Exception exception) {
332                     //do nothing
333                 }
334             }
335         }
336
337         return null;
338     }
339
340     /**
341      * Gets configuration.
342      *
343      * @param url the url
344      * @return the configuration
345      */
346     public static FileBasedConfiguration getConfiguration(URL url) {
347         FileBasedConfiguration builder = null;
348         try {
349             ConfigurationType configType = ConfigurationUtils.getConfigType(url);
350             switch (configType) {
351                 case PROPERTIES:
352                     builder = new Configurations().fileBased(PropertiesConfiguration.class, url);
353                     break;
354                 case XML:
355                     builder = new Configurations().fileBased(XMLConfiguration.class, url);
356                     break;
357                 case JSON:
358                     builder = new Configurations().fileBased(JsonConfiguration.class, url);
359                     break;
360                 case YAML:
361                     builder = new Configurations().fileBased(YamlConfiguration.class, url);
362                     break;
363                 default:
364                     throw new ConfigurationException("Configuration type not supported:"+ configType);
365             }
366         } catch (ConfigurationException exception) {
367             exception.printStackTrace();
368         }
369         return builder;
370     }
371
372     /**
373      * Gets configuration.
374      *
375      * @param file the file
376      * @return the configuration
377      */
378     public static FileBasedConfiguration getConfiguration(File file) {
379         FileBasedConfiguration builder = null;
380         try {
381             ConfigurationType configType = ConfigurationUtils.getConfigType(file);
382             switch (configType) {
383                 case PROPERTIES:
384                     builder = new Configurations().fileBased(PropertiesConfiguration.class, file);
385                     break;
386                 case XML:
387                     builder = new Configurations().fileBased(XMLConfiguration.class, file);
388                     break;
389                 case JSON:
390                     builder = new Configurations().fileBased(JsonConfiguration.class, file);
391                     break;
392                 case YAML:
393                     builder = new Configurations().fileBased(YamlConfiguration.class, file);
394                     break;
395                 default:
396                     throw new ConfigurationException("Configuration type not supported:"+ configType);
397             }
398         } catch (ConfigurationException exception) {
399             exception.printStackTrace();
400         }
401         return builder;
402     }
403
404     /**
405      * Gets collection generic type.
406      *
407      * @param field the field
408      * @return the collection generic type
409      */
410     public static Class getCollectionGenericType(Field field) {
411         Type type = field.getGenericType();
412
413         if (type instanceof ParameterizedType) {
414
415             ParameterizedType paramType = (ParameterizedType) type;
416             Type[] arr = paramType.getActualTypeArguments();
417
418             for (Type tp : arr) {
419                 Class<?> clzz = (Class<?>) tp;
420                 if (isWrapperClass(clzz)) {
421                     return clzz;
422                 } else {
423                     throw new RuntimeException("Collection of type " + clzz.getName() + " not supported.");
424                 }
425             }
426         }
427         return String[].class;
428     }
429
430     /**
431      * Gets array class.
432      *
433      * @param clazz the clazz
434      * @return the array class
435      */
436     public static Class getArrayClass(Class clazz) {
437         switch (clazz.getName()) {
438             case "java.lang.Byte":
439                 return Byte[].class;
440             case "java.lang.Short":
441                 return Short[].class;
442             case "java.lang.Integer":
443                 return Integer[].class;
444             case "java.lang.Long":
445                 return Long[].class;
446             case "java.lang.Float":
447                 return Float[].class;
448             case "java.lang.Double":
449                 return Double[].class;
450             case "java.lang.Boolean":
451                 return Boolean[].class;
452             case "java.lang.Character":
453                 return Character[].class;
454             case "java.lang.String":
455                 return String[].class;
456             default:
457                 return null;
458         }
459     }
460
461     /**
462      * Gets all class path resources.
463      *
464      * @return the all class path resources
465      */
466     public static List<URL> getAllClassPathResources() {
467         return CPScanner.scanResources(new ResourceFilter());
468     }
469
470     /**
471      * Execute ddlsql boolean.
472      *
473      * @param sql the sql
474      * @return the boolean
475      * @throws Exception the exception
476      */
477     public static boolean executeDdlSql(String sql) throws Exception {
478         DataSource datasource = ConfigurationDataSource.lookup();
479         if (datasource == null) {
480             System.err.println("DB configuration not found. Configuration management will be using "
481                     + "in-memory persistence.");
482             return false;
483         }
484         try (Connection con = datasource.getConnection(); Statement stmt = con.createStatement()) {
485             stmt.executeQuery(sql);
486         } catch (Exception exception) {
487             System.err.println("Datasource initialization error. Configuration management will be using in-memory persistence.");
488             return false;
489         }
490         return true;
491     }
492
493     /**
494      * Gets configuration builder.
495      *
496      * @param url the url
497      * @return the configuration builder
498      */
499     public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(URL url) {
500         ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder = null;
501         ConfigurationType configType = ConfigurationUtils.getConfigType(url);
502         switch (configType) {
503             case PROPERTIES:
504                 builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(
505                         PropertiesConfiguration.class);
506                 break;
507             case XML:
508                 builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(
509                         XMLConfiguration.class);
510                 break;
511             case JSON:
512                 builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(
513                         JsonConfiguration.class);
514                 break;
515             case YAML:
516                 builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(
517                         YamlConfiguration.class);
518                 break;
519             default:
520                 throw new IllegalArgumentException("Configuration type not supported:"+ configType);
521         }
522         builder.configure(new Parameters().fileBased().setURL(url)
523                 .setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
524         return builder;
525     }
526
527     /**
528      * Gets configuration builder.
529      *
530      * @param file     the file
531      * @param autoSave the auto save
532      * @return the configuration builder
533      */
534     public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(File file,
535                                                                                             boolean autoSave) {
536         ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder = null;
537         ConfigurationType configType = ConfigurationUtils.getConfigType(file);
538         switch (configType) {
539             case PROPERTIES:
540                 builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(
541                         PropertiesConfiguration.class);
542                 break;
543             case XML:
544                 builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(
545                         XMLConfiguration.class);
546                 break;
547             case JSON:
548                 builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(
549                         JsonConfiguration.class);
550                 break;
551             case YAML:
552                 builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(
553                         YamlConfiguration.class);
554                 break;
555             default:
556                 throw new IllegalArgumentException("Configuration type not supported:"+ configType);
557         }
558         builder.configure(new Parameters().fileBased().setFile(file)
559                 .setListDelimiterHandler(new DefaultListDelimiterHandler(',')));
560         builder.setAutoSave(autoSave);
561         return builder;
562     }
563
564
565     /**
566      * Execute select sql collection.
567      *
568      * @param sql    the sql
569      * @param params the params
570      * @return the collection
571      * @throws Exception the exception
572      */
573     public static Collection<String> executeSelectSql(String sql, String[] params) throws Exception {
574         Collection<String> coll = new ArrayList<>();
575         DataSource datasource = ConfigurationDataSource.lookup();
576         try (Connection con = datasource.getConnection();
577              PreparedStatement stmt = con.prepareStatement(sql)) {
578             if (params != null) {
579                 for (int i = 0; i < params.length; i++) {
580                     stmt.setString(i + 1, params[i]);
581                 }
582             }
583
584             try (ResultSet rs = stmt.executeQuery()) {
585
586                 while (rs.next()) {
587                     coll.add(rs.getString(1));
588                 }
589             }
590
591         } catch (Exception exception) {
592             //exception.printStackTrace();
593             return null;
594         }
595
596         return coll;
597     }
598
599     /**
600      * Execute insert sql boolean.
601      *
602      * @param sql    the sql
603      * @param params the params
604      * @return the boolean
605      * @throws Exception the exception
606      */
607     public static boolean executeInsertSql(String sql, Object[] params) throws Exception {
608         Collection<String> coll = new ArrayList<>();
609         DataSource datasource = ConfigurationDataSource.lookup();
610         try (Connection con = datasource.getConnection();
611              PreparedStatement stmt = con.prepareStatement(sql)) {
612             if (params != null) {
613                 int counter = 0;
614                 for (Object obj : params) {
615                     if (obj == null) {
616                         obj = "";
617                     }
618                     switch (obj.getClass().getName()) {
619                         case "java.lang.String":
620                             stmt.setString(++counter, obj.toString());
621                             break;
622                         case "java.lang.Integer":
623                             stmt.setInt(++counter, ((Integer) obj).intValue());
624                             break;
625                         case "java.lang.Long":
626                             stmt.setLong(++counter, ((Long) obj).longValue());
627                             break;
628                         default:
629                             stmt.setString(++counter, obj.toString());
630                             break;
631                     }
632                 }
633             }
634             stmt.executeUpdate();
635             return true;
636         } catch (Exception exception) {
637             exception.printStackTrace();
638         }
639         return false;
640     }
641
642     /**
643      * Read t.
644      *
645      * @param <T>       the type parameter
646      * @param config    the config
647      * @param clazz     the clazz
648      * @param keyPrefix the key prefix
649      * @return the t
650      * @throws Exception the exception
651      */
652     public static <T> T read(Configuration config, Class<T> clazz, String keyPrefix)
653             throws Exception {
654         org.openecomp.config.api.Config confAnnot =
655                 clazz.getAnnotation(org.openecomp.config.api.Config.class);
656         if (confAnnot != null) {
657             keyPrefix += (confAnnot.key() + ".");
658         }
659         T objToReturn = clazz.newInstance();
660         for (Field field : clazz.getDeclaredFields()) {
661             org.openecomp.config.api.Config fieldConfAnnot =
662                     field.getAnnotation(org.openecomp.config.api.Config.class);
663             if (fieldConfAnnot != null) {
664                 field.setAccessible(true);
665                 field.set(objToReturn, config.getProperty(keyPrefix + fieldConfAnnot.key()));
666             } else if (field.getType().getAnnotation(org.openecomp.config.api.Config.class) != null) {
667                 field.set(objToReturn, read(config, field.getType(), keyPrefix));
668             }
669         }
670         return objToReturn;
671     }
672
673     /**
674      * Gets db configuration builder.
675      *
676      * @param configName the config name
677      * @return the db configuration builder
678      * @throws Exception the exception
679      */
680     public static BasicConfigurationBuilder<AgglomerateConfiguration> getDbConfigurationBuilder(
681             String configName) throws Exception {
682         Configuration dbConfig = ConfigurationRepository.lookup()
683                 .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE);
684         BasicConfigurationBuilder<AgglomerateConfiguration> builder =
685                 new BasicConfigurationBuilder<AgglomerateConfiguration>(AgglomerateConfiguration.class);
686         builder.configure(
687                 new Parameters().database()
688                         .setDataSource(ConfigurationDataSource.lookup())
689                         .setTable(dbConfig.getString("config.Table"))
690                         .setKeyColumn(dbConfig.getString("configKey"))
691                         .setValueColumn(dbConfig.getString("configValue"))
692                         .setConfigurationNameColumn(dbConfig.getString("configNameColumn"))
693                         .setConfigurationName(configName)
694                         .setAutoCommit(true)
695         );
696         return builder;
697     }
698
699     /**
700      * Gets property.
701      *
702      * @param config          the config
703      * @param key             the key
704      * @param processingHints the processing hints
705      * @return the property
706      */
707     public static Object getProperty(Configuration config, String key, int processingHints) {
708         if (!isDirectLookup(processingHints)) {
709             if (config instanceof AgglomerateConfiguration) {
710                 return ((AgglomerateConfiguration) config).getPropertyValue(key);
711             } else if (config instanceof CompositeConfiguration) {
712                 CompositeConfiguration conf = (CompositeConfiguration) config;
713                 for (int i = 0; i < conf.getNumberOfConfigurations(); i++) {
714                     if (conf.getConfiguration(i) instanceof AgglomerateConfiguration) {
715                         return ((AgglomerateConfiguration) conf.getConfiguration(i)).getPropertyValue(key);
716                     } else if (isNodeSpecific(processingHints)) {
717                         Object obj = conf.getConfiguration(i).getProperty(key);
718                         if (obj != null) {
719                             return obj;
720                         }
721                     }
722                 }
723             }
724         }
725         return config.getProperty(key);
726     }
727
728     /**
729      * Gets primitive array.
730      *
731      * @param collection the collection
732      * @param clazz      the clazz
733      * @return the primitive array
734      */
735     public static Object getPrimitiveArray(Collection collection, Class clazz) {
736
737         if (clazz == int.class) {
738             int[] array = new int[collection.size()];
739             Object[] objArray = collection.toArray();
740             for (int i = 0; i < collection.size(); i++) {
741                 array[i] = (int) objArray[i];
742             }
743             return array;
744         }
745         if (clazz == byte.class) {
746             byte[] array = new byte[collection.size()];
747             Object[] objArray = collection.toArray();
748             for (int i = 0; i < collection.size(); i++) {
749                 array[i] = (byte) objArray[i];
750             }
751             return array;
752         }
753         if (clazz == short.class) {
754             short[] array = new short[collection.size()];
755             Object[] objArray = collection.toArray();
756             for (int i = 0; i < collection.size(); i++) {
757                 array[i] = (short) objArray[i];
758             }
759             return array;
760         }
761         if (clazz == long.class) {
762             long[] array = new long[collection.size()];
763             Object[] objArray = collection.toArray();
764             for (int i = 0; i < collection.size(); i++) {
765                 array[i] = (long) objArray[i];
766             }
767             return array;
768         }
769         if (clazz == float.class) {
770             float[] array = new float[collection.size()];
771             Object[] objArray = collection.toArray();
772             for (int i = 0; i < collection.size(); i++) {
773                 array[i] = (float) objArray[i];
774             }
775             return array;
776         }
777         if (clazz == double.class) {
778             double[] array = new double[collection.size()];
779             Object[] objArray = collection.toArray();
780             for (int i = 0; i < collection.size(); i++) {
781                 array[i] = (double) objArray[i];
782             }
783             return array;
784         }
785         if (clazz == boolean.class) {
786             boolean[] array = new boolean[collection.size()];
787             Object[] objArray = collection.toArray();
788             for (int i = 0; i < collection.size(); i++) {
789                 array[i] = (boolean) objArray[i];
790             }
791             return array;
792         }
793         Object obj = null;
794         return obj;
795     }
796
797     /**
798      * Is wrapper class boolean.
799      *
800      * @param clazz the clazz
801      * @return the boolean
802      */
803     public static boolean isWrapperClass(Class clazz) {
804         return clazz == String.class || clazz == Boolean.class || clazz == Character.class
805                 || Number.class.isAssignableFrom(clazz);
806     }
807
808     /**
809      * Gets collection string.
810      *
811      * @param input the input
812      * @return the collection string
813      */
814     public static String getCollectionString(String input) {
815         Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
816         Matcher matcher = pattern.matcher(input);
817         if (matcher.matches()) {
818             input = matcher.group(1);
819         }
820         return input;
821     }
822
823     /**
824      * Is collection boolean.
825      *
826      * @param input the input
827      * @return the boolean
828      */
829     public static boolean isCollection(String input) {
830         Pattern pattern = Pattern.compile("^\\[(.*)\\]$");
831         Matcher matcher = pattern.matcher(input);
832         return matcher.matches();
833     }
834
835     /**
836      * Process variables if present string.
837      *
838      * @param tenant    the tenant
839      * @param namespace the namespace
840      * @param data      the data
841      * @return the string
842      */
843     public static String processVariablesIfPresent(String tenant, String namespace, String data) {
844         Pattern pattern = Pattern.compile("^.*\\$\\{(.*)\\}.*");
845         Matcher matcher = pattern.matcher(data);
846         if (matcher.matches()) {
847             String key = matcher.group(1);
848             if (key.toUpperCase().startsWith("ENV:")) {
849                 String envValue = System.getenv(key.substring(4));
850                 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
851                         envValue == null ? "" : envValue.replace("\\", "\\\\")));
852             } else if (key.toUpperCase().startsWith("SYS:")) {
853                 String sysValue = System.getProperty(key.substring(4));
854                 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
855                         sysValue == null ? "" : sysValue.replace("\\", "\\\\")));
856             } else {
857                 String propertyValue = ConfigurationUtils.getCollectionString(
858                         ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key).toString());
859                 return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}",
860                         propertyValue == null ? "" : propertyValue.replace("\\", "\\\\")));
861             }
862         } else {
863             return data;
864         }
865     }
866
867     /**
868      * Gets file contents.
869      *
870      * @param path the path
871      * @return the file contents
872      */
873     public static String getFileContents(String path) {
874         try {
875             if (path != null) {
876                 return IOUtils.toString(new URL(path));
877             }
878         } catch (Exception exception) {
879             exception.printStackTrace();
880         }
881         return null;
882     }
883
884     /**
885      * Gets file contents.
886      *
887      * @param path the path
888      * @return the file contents
889      */
890     public static String getFileContents(Path path) {
891         try {
892             if (path != null) {
893                 return new String(Files.readAllBytes(path));
894             }
895         } catch (Exception exception) {
896             exception.printStackTrace();
897         }
898         return null;
899     }
900
901     /**
902      * Gets concrete collection.
903      *
904      * @param clazz the clazz
905      * @return the concrete collection
906      */
907     public static Collection getConcreteCollection(Class clazz) {
908         switch (clazz.getName()) {
909             case "java.util.Collection":
910             case "java.util.List":
911                 return new ArrayList<>();
912             case "java.util.Set":
913                 return new HashSet<>();
914             case "java.util.SortedSet":
915                 return new TreeSet<>();
916             case "java.util.Queue":
917                 return new ConcurrentLinkedQueue<>();
918             case "java.util.Deque":
919                 return new ArrayDeque<>();
920             case "java.util.concurrent.TransferQueue":
921                 return new LinkedTransferQueue<>();
922             case "java.util.concurrent.BlockingQueue":
923                 return new LinkedBlockingQueue<>();
924             default:
925                 return null;
926         }
927     }
928
929     /**
930      * Gets default for.
931      *
932      * @param clazz the clazz
933      * @return the default for
934      */
935     public static Object getDefaultFor(Class clazz) {
936         if (byte.class == clazz) {
937             return new Byte("0");
938         } else if (short.class == clazz) {
939             return new Short("0");
940         } else if (int.class == clazz) {
941             return new Integer("0");
942         } else if (float.class == clazz) {
943             return new Float("0");
944         } else if (long.class == clazz) {
945             return new Long("0");
946         } else if (double.class == clazz) {
947             return new Double("0");
948         } else if (boolean.class == clazz) {
949             return Boolean.FALSE;
950         }
951         return new Character((char) 0);
952     }
953
954     /**
955      * Gets compatible collection for abstract def.
956      *
957      * @param clazz the clazz
958      * @return the compatible collection for abstract def
959      */
960     public static Collection getCompatibleCollectionForAbstractDef(Class clazz) {
961         if (BlockingQueue.class.isAssignableFrom(clazz)) {
962             return getConcreteCollection(BlockingQueue.class);
963         }
964         if (TransferQueue.class.isAssignableFrom(clazz)) {
965             return getConcreteCollection(TransferQueue.class);
966         }
967         if (Deque.class.isAssignableFrom(clazz)) {
968             return getConcreteCollection(Deque.class);
969         }
970         if (Queue.class.isAssignableFrom(clazz)) {
971             return getConcreteCollection(Queue.class);
972         }
973         if (SortedSet.class.isAssignableFrom(clazz)) {
974             return getConcreteCollection(SortedSet.class);
975         }
976         if (Set.class.isAssignableFrom(clazz)) {
977             return getConcreteCollection(Set.class);
978         }
979         if (List.class.isAssignableFrom(clazz)) {
980             return getConcreteCollection(List.class);
981         }
982         return null;
983     }
984
985     /**
986      * Gets configuration repository key.
987      *
988      * @param array the array
989      * @return the configuration repository key
990      */
991     public static String getConfigurationRepositoryKey(String[] array) {
992         Stack<String> stack = new Stack<>();
993         stack.push(Constants.DEFAULT_TENANT);
994         for (String element : array) {
995             stack.push(element);
996         }
997         String toReturn = stack.pop();
998         return stack.pop() + Constants.KEY_ELEMENTS_DELEMETER + toReturn;
999     }
1000
1001     /**
1002      * Gets configuration repository key.
1003      *
1004      * @param file the file
1005      * @return the configuration repository key
1006      */
1007     public static String getConfigurationRepositoryKey(File file) {
1008         return getConfigurationRepositoryKey(
1009                 ConfigurationUtils.getNamespace(file).split(Constants.TENANT_NAMESPACE_SAPERATOR));
1010     }
1011
1012     /**
1013      * Gets configuration repository key.
1014      *
1015      * @param url the url
1016      * @return the configuration repository key
1017      */
1018     public static String getConfigurationRepositoryKey(URL url) {
1019         return getConfigurationRepositoryKey(
1020                 ConfigurationUtils.getNamespace(url).split(Constants.TENANT_NAMESPACE_SAPERATOR));
1021     }
1022
1023     /**
1024      * To map linked hash map.
1025      *
1026      * @param config the config
1027      * @return the linked hash map
1028      */
1029     public static LinkedHashMap toMap(Configuration config) {
1030         Iterator<String> iterator = config.getKeys();
1031         LinkedHashMap<String, String> map = new LinkedHashMap<>();
1032         while (iterator.hasNext()) {
1033             String key = iterator.next();
1034             if (!(key.equals(Constants.MODE_KEY) || key.equals(Constants.NAMESPACE_KEY)
1035                     || key.equals(Constants.LOAD_ORDER_KEY))) {
1036                 map.put(key, config.getProperty(key).toString());
1037             }
1038         }
1039
1040         return map;
1041     }
1042
1043     /**
1044      * Diff map.
1045      *
1046      * @param orig   the orig
1047      * @param latest the latest
1048      * @return the map
1049      */
1050     public static Map diff(LinkedHashMap orig, LinkedHashMap latest) {
1051         orig = new LinkedHashMap<>(orig);
1052         latest = new LinkedHashMap<>(latest);
1053         List<String> set = new ArrayList(orig.keySet());
1054         for (String key : set) {
1055             if (latest.remove(key, orig.get(key))) {
1056                 orig.remove(key);
1057             }
1058         }
1059         Set<String> keys = latest.keySet();
1060         for (String key : keys) {
1061             orig.remove(key);
1062         }
1063         set = new ArrayList(orig.keySet());
1064         for (String key : set) {
1065             latest.put(key, "");
1066         }
1067         return new HashMap<>(latest);
1068     }
1069
1070     /**
1071      * Is array boolean.
1072      *
1073      * @param tenant          the tenant
1074      * @param namespace       the namespace
1075      * @param key             the key
1076      * @param processingHints the processing hints
1077      * @return the boolean
1078      * @throws Exception the exception
1079      */
1080     public static boolean isArray(String tenant, String namespace, String key, int processingHints)
1081             throws Exception {
1082         Object obj = ConfigurationUtils
1083                 .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace), key,
1084                         processingHints);
1085         return (obj == null) ? false : ConfigurationUtils.isCollection(obj.toString());
1086     }
1087
1088     /**
1089      * Is direct lookup boolean.
1090      *
1091      * @param hints the hints
1092      * @return the boolean
1093      */
1094     public static boolean isDirectLookup(int hints) {
1095         return (hints & LATEST_LOOKUP.value()) == LATEST_LOOKUP.value();
1096     }
1097
1098     /**
1099      * Is external lookup boolean.
1100      *
1101      * @param hints the hints
1102      * @return the boolean
1103      */
1104     public static boolean isExternalLookup(int hints) {
1105         return (hints & EXTERNAL_LOOKUP.value()) == EXTERNAL_LOOKUP.value();
1106     }
1107
1108     /**
1109      * Is node specific boolean.
1110      *
1111      * @param hints the hints
1112      * @return the boolean
1113      */
1114     public static boolean isNodeSpecific(int hints) {
1115         return (hints & NODE_SPECIFIC.value()) == NODE_SPECIFIC.value();
1116     }
1117
1118     public static boolean isZeroLengthArray(Class clazz, Object obj) {
1119         if (clazz.isArray() && clazz.getComponentType().isPrimitive()) {
1120             if (clazz.getComponentType() == int.class) {
1121                 return ((int[]) obj).length == 0;
1122             } else if (clazz.getComponentType() == byte.class) {
1123                 return ((byte[]) obj).length == 0;
1124             } else if (clazz.getComponentType() == short.class) {
1125                 return ((short[]) obj).length == 0;
1126             } else if (clazz.getComponentType() == float.class) {
1127                 return ((float[]) obj).length == 0;
1128             } else if (clazz.getComponentType() == boolean.class) {
1129                 return ((boolean[]) obj).length == 0;
1130             } else if (clazz.getComponentType() == double.class) {
1131                 return ((double[]) obj).length == 0;
1132             } else if (clazz.getComponentType() == long.class) {
1133                 return ((long[]) obj).length == 0;
1134             } else {
1135                 return ((Object[]) obj).length == 0;
1136             }
1137         }
1138
1139         return false;
1140     }
1141
1142     /**
1143      * Checks if value is blank
1144      *
1145      * @param value
1146      * @return
1147      */
1148     public static boolean isBlank(String value) {
1149         return value == null || value.trim().length() == 0;
1150     }
1151 }