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