diff options
author | amitjai <amitjai@amdocs.com> | 2018-04-27 13:28:57 +0530 |
---|---|---|
committer | Oren Kleks <orenkle@amdocs.com> | 2018-04-30 06:05:27 +0000 |
commit | 42c920baf4dbb9fe8775843a6d4c9f70fa29f064 (patch) | |
tree | ac2aff977e2b129e61d2166c4832842676e4f5c3 /common/onap-common-configuration-management/onap-configuration-management-core/src | |
parent | f487427a32f410ab5c97a4092865d32beb88ee27 (diff) |
Rename packages from openecomp to onap.
This task is all about package name space change also make changes to pom for common module
Change-Id: Ie9bda0f958a9a05826c0374830cc9cb7d6d196b6
Issue-ID: SDC-1272
Signed-off-by: amitjai <amitjai@amdocs.com>
Diffstat (limited to 'common/onap-common-configuration-management/onap-configuration-management-core/src')
21 files changed, 3769 insertions, 0 deletions
diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/ConfigurationUtils.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/ConfigurationUtils.java new file mode 100644 index 0000000000..7f22461cda --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/ConfigurationUtils.java @@ -0,0 +1,1144 @@ +package org.onap.config; + +import com.google.common.collect.ImmutableMap; +import com.virtlink.commons.configuration2.jackson.JsonConfiguration; +import net.sf.corn.cps.CPScanner; +import net.sf.corn.cps.ResourceFilter; +import org.apache.commons.configuration2.CompositeConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.FileBasedConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.XMLConfiguration; +import org.apache.commons.configuration2.builder.BasicConfigurationBuilder; +import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder; +import org.apache.commons.configuration2.builder.fluent.Configurations; +import org.apache.commons.configuration2.builder.fluent.Parameters; +import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.io.IOUtils; +import org.onap.config.api.Config; +import org.onap.config.api.ConfigurationManager; +import org.onap.config.impl.ConfigurationRepository; +import org.onap.config.impl.YamlConfiguration; +import org.onap.config.impl.AgglomerateConfiguration; +import org.onap.config.impl.ConfigurationDataSource; +import org.onap.config.type.ConfigurationMode; +import org.onap.config.type.ConfigurationType; + +import javax.sql.DataSource; +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.LinkedTransferQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TransferQueue; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.google.common.collect.ImmutableMap.builder; +import static org.onap.config.api.Hint.EXTERNAL_LOOKUP; +import static org.onap.config.api.Hint.LATEST_LOOKUP; +import static org.onap.config.api.Hint.NODE_SPECIFIC; + +/** + * The type Configuration utils. + */ +public class ConfigurationUtils { + + private ConfigurationUtils() { + } + + private static ImmutableMap<Class,Class> arrayClassMap; + + static { + ImmutableMap.Builder<Class,Class> builder = builder(); + builder.put(Byte.class,Byte[].class).put(Short.class, Short[].class) + .put(Integer.class,Integer[].class).put(Long.class,Long[].class) + .put(Float.class,Float[].class).put(Double.class,Double[].class) + .put(Boolean.class,Boolean[].class).put(Character.class,Character[].class) + .put(String.class,String[].class); + arrayClassMap = builder.build(); + } + + /** + * Gets thread factory. + * + * @return the thread factory + */ + public static ThreadFactory getThreadFactory() { + return (r1) -> { + Thread thread = Executors.privilegedThreadFactory().newThread(r1); + thread.setDaemon(true); + return thread; + }; + } + + /** + * Gets all files. + * + * @param file the file + * @param recursive the recursive + * @param onlyDirectory the only directory + * @return the all files + */ + public static Collection<File> getAllFiles(File file, boolean recursive, boolean onlyDirectory) { + ArrayList<File> collection = new ArrayList<>(); + if (file.isDirectory() && file.exists()) { + File[] files = file.listFiles(); + for (File innerFile : files) { + if (innerFile.isFile() && !onlyDirectory) { + collection.add(innerFile); + } else if (innerFile.isDirectory()) { + collection.add(innerFile); + if (recursive) { + collection.addAll(getAllFiles(innerFile, recursive, onlyDirectory)); + } + } + } + } + return collection; + } + + /** + * Gets comma saperated list. + * + * @param list the list + * @return the comma separated list + */ + public static String getCommaSeparatedList(List list) { + return ((Stream<String>) list.stream().filter(o -> o != null && !o.toString().trim().isEmpty()).map(o -> o.toString().trim())).collect(Collectors.joining(",")); + } + + /** + * Gets comma saperated list. + * + * @param list the list + * @return the comma saperated list + */ + public static String getCommaSeparatedList(String[] list) { + return getCommaSeparatedList(list == null ? Arrays.asList() : Arrays.asList(list)); + } + + /** + * Gets config type. + * + * @param url the url + * @return the config type + */ + public static ConfigurationType getConfigType(URL url) { + return Enum.valueOf(ConfigurationType.class, + url.getFile().substring(url.getFile().lastIndexOf('.') + 1).toUpperCase()); + } + + /** + * Gets config type. + * + * @param file the file + * @return the config type + */ + public static ConfigurationType getConfigType(File file) { + return Enum.valueOf(ConfigurationType.class, + file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf('.') + 1) + .toUpperCase()); + } + + /** + * Is config boolean. + * + * @param url the url + * @return the boolean + */ + public static boolean isConfig(URL url) { + return isConfig(url.getFile()); + } + + /** + * Is config boolean. + * + * @param file the file + * @return the boolean + */ + public static boolean isConfig(File file) { + return file != null && file.exists() && isConfig(file.getName()); + } + + /** + * Is config boolean. + * + * @param file the file + * @return the boolean + */ + public static boolean isConfig(String file) { + file = file.toUpperCase().substring(file.lastIndexOf('!') + 1); + file = file.substring(file.lastIndexOf('/') + 1); + return file.matches( + "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE + + "|" + ConfigurationMode.UNION + ")){0,1}" + "\\.(" + + ConfigurationType.PROPERTIES.name() + "|" + ConfigurationType.XML.name() + "|" + + ConfigurationType.JSON.name() + "|" + ConfigurationType.YAML.name() + ")$") + || file.matches("CONFIG(.)*\\.(" + ConfigurationType.PROPERTIES.name() + "|" + + ConfigurationType.XML.name() + "|" + ConfigurationType.JSON.name() + "|" + + ConfigurationType.YAML.name() + ")$"); + } + + /** + * Gets namespace. + * + * @param url the url + * @return the namespace + */ + public static String getNamespace(URL url) { + String namespace = getNamespace(getConfiguration(url)); + if (namespace != null) { + return namespace.toUpperCase(); + } + return getNamespace(url.getFile().toUpperCase()); + } + + /** + * Gets namespace. + * + * @param file the file + * @return the namespace + */ + public static String getNamespace(File file) { + String namespace = getNamespace(getConfiguration(file)); + if (namespace != null) { + return namespace.toUpperCase(); + } + return getNamespace(file.getName().toUpperCase()); + } + + private static String getNamespace(Configuration config) { + return config.getString(Constants.NAMESPACE_KEY) == null ? null + : config.getString(Constants.NAMESPACE_KEY).toUpperCase(); + } + + /** + * Gets namespace. + * + * @param file the file + * @return the namespace + */ + public static String getNamespace(String file) { + file = file.toUpperCase().substring(file.lastIndexOf('!') + 1); + file = file.substring(file.lastIndexOf('/') + 1); + Pattern pattern = Pattern.compile( + "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE + + "|" + ConfigurationMode.UNION + ")){0,1}" + "\\.(" + + ConfigurationType.PROPERTIES.name() + "|" + ConfigurationType.XML.name() + "|" + + ConfigurationType.JSON.name() + "|" + ConfigurationType.YAML.name() + ")$"); + Matcher matcher = pattern.matcher(file); + boolean b1 = matcher.matches(); + if (b1) { + if (matcher.group(1) != null) { + String moduleName = matcher.group(1).substring(1); + return moduleName.equalsIgnoreCase(ConfigurationMode.OVERRIDE.name()) + || moduleName.equalsIgnoreCase(ConfigurationMode.UNION.name()) + || moduleName.equalsIgnoreCase(ConfigurationMode.MERGE.name()) + ? Constants.DEFAULT_NAMESPACE : moduleName; + } else { + return Constants.DEFAULT_NAMESPACE; + } + } else if (isConfig(file)) { + return Constants.DEFAULT_NAMESPACE; + } + + return null; + } + + /** + * Gets merge strategy. + * + * @param url the url + * @return the merge strategy + */ + public static ConfigurationMode getMergeStrategy(URL url) { + String configMode = getMergeStrategy(getConfiguration(url)); + if (configMode != null) { + try { + return Enum.valueOf(ConfigurationMode.class, configMode); + } catch (Exception exception) { + //do nothing + } + } + return getMergeStrategy(url.getFile().toUpperCase()); + } + + private static String getMergeStrategy(Configuration config) { + return config.getString(Constants.MODE_KEY) == null ? null + : config.getString(Constants.MODE_KEY).toUpperCase(); + } + + /** + * Gets merge strategy. + * + * @param file the file + * @return the merge strategy + */ + public static ConfigurationMode getMergeStrategy(File file) { + String configMode = getMergeStrategy(getConfiguration(file)); + if (configMode != null) { + try { + return Enum.valueOf(ConfigurationMode.class, configMode); + } catch (Exception exception) { + //do nothing + } + } + return getMergeStrategy(file.getName().toUpperCase()); + } + + /** + * Gets merge strategy. + * + * @param file the file + * @return the merge strategy + */ + public static ConfigurationMode getMergeStrategy(String file) { + file = file.toUpperCase().substring(file.lastIndexOf('!') + 1); + file = file.substring(file.lastIndexOf('/') + 1); + Pattern pattern = Pattern.compile( + "CONFIG(-\\w*){0,1}(-" + "(" + ConfigurationMode.OVERRIDE + "|" + ConfigurationMode.MERGE + + "|" + ConfigurationMode.UNION + ")){0,1}" + "\\.(" + + ConfigurationType.PROPERTIES.name() + "|" + ConfigurationType.XML.name() + "|" + + ConfigurationType.JSON.name() + "|" + ConfigurationType.YAML.name() + ")$"); + Matcher matcher = pattern.matcher(file); + boolean b1 = matcher.matches(); + if (b1) { + for (int i = 1; i <= matcher.groupCount(); i++) { + String modeName = matcher.group(i); + if (modeName != null) { + modeName = modeName.substring(1); + } + try { + return Enum.valueOf(ConfigurationMode.class, modeName); + } catch (Exception exception) { + //do nothing + } + } + } + + return null; + } + + /** + * Gets configuration. + * + * @param url the url + * @return the configuration + */ + public static FileBasedConfiguration getConfiguration(URL url) { + FileBasedConfiguration builder = null; + try { + ConfigurationType configType = ConfigurationUtils.getConfigType(url); + switch (configType) { + case PROPERTIES: + builder = new Configurations().fileBased(PropertiesConfiguration.class, url); + break; + case XML: + builder = new Configurations().fileBased(XMLConfiguration.class, url); + break; + case JSON: + builder = new Configurations().fileBased(JsonConfiguration.class, url); + break; + case YAML: + builder = new Configurations().fileBased(YamlConfiguration.class, url); + break; + default: + throw new ConfigurationException("Configuration type not supported:"+ configType); + } + } catch (ConfigurationException exception) { + exception.printStackTrace(); + } + return builder; + } + + /** + * Gets configuration. + * + * @param file the file + * @return the configuration + */ + public static FileBasedConfiguration getConfiguration(File file) { + FileBasedConfiguration builder = null; + try { + ConfigurationType configType = ConfigurationUtils.getConfigType(file); + switch (configType) { + case PROPERTIES: + builder = new Configurations().fileBased(PropertiesConfiguration.class, file); + break; + case XML: + builder = new Configurations().fileBased(XMLConfiguration.class, file); + break; + case JSON: + builder = new Configurations().fileBased(JsonConfiguration.class, file); + break; + case YAML: + builder = new Configurations().fileBased(YamlConfiguration.class, file); + break; + default: + throw new ConfigurationException("Configuration type not supported:"+ configType); + } + } catch (ConfigurationException exception) { + exception.printStackTrace(); + } + return builder; + } + + /** + * Gets collection generic type. + * + * @param field the field + * @return the collection generic type + */ + public static Class getCollectionGenericType(Field field) { + Type type = field.getGenericType(); + + if (type instanceof ParameterizedType) { + + ParameterizedType paramType = (ParameterizedType) type; + Type[] arr = paramType.getActualTypeArguments(); + + for (Type tp : arr) { + Class<?> clzz = (Class<?>) tp; + if (isWrapperClass(clzz)) { + return clzz; + } else { + throw new RuntimeException("Collection of type " + clzz.getName() + " not supported."); + } + } + } + return String[].class; + } + + + + /** + * Gets array class. + * + * @param clazz the clazz + * @return the array class + */ + public static Class getArrayClass(Class clazz) { + return arrayClassMap.getOrDefault(clazz, null); + } + + /** + * Gets all class path resources. + * + * @return the all class path resources + */ + public static List<URL> getAllClassPathResources() { + return CPScanner.scanResources(new ResourceFilter()); + } + + /** + * Execute ddlsql boolean. + * + * @param sql the sql + * @return the boolean + * @throws Exception the exception + */ + public static boolean executeDdlSql(String sql) throws Exception { + DataSource datasource = ConfigurationDataSource.lookup(); + if (datasource == null) { + System.err.println("DB configuration not found. Configuration management will be using " + + "in-memory persistence."); + return false; + } + try (Connection con = datasource.getConnection(); Statement stmt = con.createStatement()) { + stmt.executeQuery(sql); + } catch (Exception exception) { + System.err.println("Datasource initialization error. Configuration management will be using in-memory persistence."); + return false; + } + return true; + } + + /** + * Gets configuration builder. + * + * @param url the url + * @return the configuration builder + */ + public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(URL url) { + ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder = null; + ConfigurationType configType = ConfigurationUtils.getConfigType(url); + switch (configType) { + case PROPERTIES: + builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>( + PropertiesConfiguration.class); + break; + case XML: + builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>( + XMLConfiguration.class); + break; + case JSON: + builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>( + JsonConfiguration.class); + break; + case YAML: + builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>( + YamlConfiguration.class); + break; + default: + throw new IllegalArgumentException("Configuration type not supported:"+ configType); + } + builder.configure(new Parameters().fileBased().setURL(url) + .setListDelimiterHandler(new DefaultListDelimiterHandler(','))); + return builder; + } + + /** + * Gets configuration builder. + * + * @param file the file + * @param autoSave the auto save + * @return the configuration builder + */ + public static BasicConfigurationBuilder<FileBasedConfiguration> getConfigurationBuilder(File file, + boolean autoSave) { + ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder = null; + ConfigurationType configType = ConfigurationUtils.getConfigType(file); + switch (configType) { + case PROPERTIES: + builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>( + PropertiesConfiguration.class); + break; + case XML: + builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>( + XMLConfiguration.class); + break; + case JSON: + builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>( + JsonConfiguration.class); + break; + case YAML: + builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>( + YamlConfiguration.class); + break; + default: + throw new IllegalArgumentException("Configuration type not supported:"+ configType); + } + builder.configure(new Parameters().fileBased().setFile(file) + .setListDelimiterHandler(new DefaultListDelimiterHandler(','))); + builder.setAutoSave(autoSave); + return builder; + } + + + /** + * Execute select sql collection. + * + * @param sql the sql + * @param params the params + * @return the collection + * @throws Exception the exception + */ + public static Collection<String> executeSelectSql(String sql, String[] params) throws Exception { + Collection<String> coll = new ArrayList<>(); + DataSource datasource = ConfigurationDataSource.lookup(); + try (Connection con = datasource.getConnection(); + PreparedStatement stmt = con.prepareStatement(sql)) { + if (params != null) { + for (int i = 0; i < params.length; i++) { + stmt.setString(i + 1, params[i]); + } + } + + try (ResultSet rs = stmt.executeQuery()) { + + while (rs.next()) { + coll.add(rs.getString(1)); + } + } + + } catch (Exception exception) { + //exception.printStackTrace(); + return null; + } + + return coll; + } + + /** + * Execute insert sql boolean. + * + * @param sql the sql + * @param params the params + * @return the boolean + * @throws Exception the exception + */ + public static boolean executeInsertSql(String sql, Object[] params) throws Exception { + Collection<String> coll = new ArrayList<>(); + DataSource datasource = ConfigurationDataSource.lookup(); + try (Connection con = datasource.getConnection(); + PreparedStatement stmt = con.prepareStatement(sql)) { + if (params != null) { + int counter = 0; + for (Object obj : params) { + if (obj == null) { + obj = ""; + } + switch (obj.getClass().getName()) { + case "java.lang.String": + stmt.setString(++counter, obj.toString()); + break; + case "java.lang.Integer": + stmt.setInt(++counter, ((Integer) obj).intValue()); + break; + case "java.lang.Long": + stmt.setLong(++counter, ((Long) obj).longValue()); + break; + default: + stmt.setString(++counter, obj.toString()); + break; + } + } + } + stmt.executeUpdate(); + return true; + } catch (Exception exception) { + exception.printStackTrace(); + } + return false; + } + + /** + * Read t. + * + * @param <T> the type parameter + * @param config the config + * @param clazz the clazz + * @param keyPrefix the key prefix + * @return the t + * @throws Exception the exception + */ + public static <T> T read(Configuration config, Class<T> clazz, String keyPrefix) + throws Exception { + Config confAnnot = + clazz.getAnnotation(Config.class); + if (confAnnot != null) { + keyPrefix += (confAnnot.key() + "."); + } + T objToReturn = clazz.newInstance(); + for (Field field : clazz.getDeclaredFields()) { + Config fieldConfAnnot = + field.getAnnotation(Config.class); + if (fieldConfAnnot != null) { + field.setAccessible(true); + field.set(objToReturn, config.getProperty(keyPrefix + fieldConfAnnot.key())); + } else if (field.getType().getAnnotation(Config.class) != null) { + field.set(objToReturn, read(config, field.getType(), keyPrefix)); + } + } + return objToReturn; + } + + /** + * Gets db configuration builder. + * + * @param configName the config name + * @return the db configuration builder + * @throws Exception the exception + */ + public static BasicConfigurationBuilder<AgglomerateConfiguration> getDbConfigurationBuilder( + String configName) throws Exception { + Configuration dbConfig = ConfigurationRepository.lookup() + .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE); + BasicConfigurationBuilder<AgglomerateConfiguration> builder = + new BasicConfigurationBuilder<AgglomerateConfiguration>(AgglomerateConfiguration.class); + builder.configure( + new Parameters().database() + .setDataSource(ConfigurationDataSource.lookup()) + .setTable(dbConfig.getString("config.Table")) + .setKeyColumn(dbConfig.getString("configKey")) + .setValueColumn(dbConfig.getString("configValue")) + .setConfigurationNameColumn(dbConfig.getString("configNameColumn")) + .setConfigurationName(configName) + .setAutoCommit(true) + ); + return builder; + } + + /** + * Gets property. + * + * @param config the config + * @param key the key + * @param processingHints the processing hints + * @return the property + */ + public static Object getProperty(Configuration config, String key, int processingHints) { + if (!isDirectLookup(processingHints)) { + if (config instanceof AgglomerateConfiguration) { + return ((AgglomerateConfiguration) config).getPropertyValue(key); + } else if (config instanceof CompositeConfiguration) { + CompositeConfiguration conf = (CompositeConfiguration) config; + for (int i = 0; i < conf.getNumberOfConfigurations(); i++) { + if (conf.getConfiguration(i) instanceof AgglomerateConfiguration) { + return ((AgglomerateConfiguration) conf.getConfiguration(i)).getPropertyValue(key); + } else if (isNodeSpecific(processingHints)) { + Object obj = conf.getConfiguration(i).getProperty(key); + if (obj != null) { + return obj; + } + } + } + } + } + return config.getProperty(key); + } + + /** + * Gets primitive array. + * + * @param collection the collection + * @param clazz the clazz + * @return the primitive array + */ + public static Object getPrimitiveArray(Collection collection, Class clazz) { + if (clazz == int.class) { + int[] array = new int[collection.size()]; + Object[] objArray = collection.toArray(); + for (int i = 0; i < collection.size(); i++) { + array[i] = (int) objArray[i]; + } + return array; + } + if (clazz == byte.class) { + byte[] array = new byte[collection.size()]; + Object[] objArray = collection.toArray(); + for (int i = 0; i < collection.size(); i++) { + array[i] = (byte) objArray[i]; + } + return array; + } + if (clazz == short.class) { + short[] array = new short[collection.size()]; + Object[] objArray = collection.toArray(); + for (int i = 0; i < collection.size(); i++) { + array[i] = (short) objArray[i]; + } + return array; + } + if (clazz == long.class) { + long[] array = new long[collection.size()]; + Object[] objArray = collection.toArray(); + for (int i = 0; i < collection.size(); i++) { + array[i] = (long) objArray[i]; + } + return array; + } + if (clazz == float.class) { + float[] array = new float[collection.size()]; + Object[] objArray = collection.toArray(); + for (int i = 0; i < collection.size(); i++) { + array[i] = (float) objArray[i]; + } + return array; + } + if (clazz == double.class) { + double[] array = new double[collection.size()]; + Object[] objArray = collection.toArray(); + for (int i = 0; i < collection.size(); i++) { + array[i] = (double) objArray[i]; + } + return array; + } + if (clazz == boolean.class) { + boolean[] array = new boolean[collection.size()]; + Object[] objArray = collection.toArray(); + for (int i = 0; i < collection.size(); i++) { + array[i] = (boolean) objArray[i]; + } + return array; + } + Object obj = null; + return obj; + } + + /** + * Is wrapper class boolean. + * + * @param clazz the clazz + * @return the boolean + */ + public static boolean isWrapperClass(Class clazz) { + return clazz == String.class || clazz == Boolean.class || clazz == Character.class + || Number.class.isAssignableFrom(clazz); + } + + /** + * Gets collection string. + * + * @param input the input + * @return the collection string + */ + public static String getCollectionString(String input) { + Pattern pattern = Pattern.compile("^\\[(.*)\\]$"); + Matcher matcher = pattern.matcher(input); + if (matcher.matches()) { + input = matcher.group(1); + } + return input; + } + + /** + * Is collection boolean. + * + * @param input the input + * @return the boolean + */ + public static boolean isCollection(String input) { + Pattern pattern = Pattern.compile("^\\[(.*)\\]$"); + Matcher matcher = pattern.matcher(input); + return matcher.matches(); + } + + /** + * Process variables if present string. + * + * @param tenant the tenant + * @param namespace the namespace + * @param data the data + * @return the string + */ + public static String processVariablesIfPresent(String tenant, String namespace, String data) { + Pattern pattern = Pattern.compile("^.*\\$\\{(.*)\\}.*"); + Matcher matcher = pattern.matcher(data); + if (matcher.matches()) { + String key = matcher.group(1); + if (key.toUpperCase().startsWith("ENV:")) { + String envValue = System.getenv(key.substring(4)); + return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}", + envValue == null ? "" : envValue.replace("\\", "\\\\"))); + } else if (key.toUpperCase().startsWith("SYS:")) { + String sysValue = System.getProperty(key.substring(4)); + return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}", + sysValue == null ? "" : sysValue.replace("\\", "\\\\"))); + } else { + String propertyValue = ConfigurationUtils.getCollectionString( + ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key).toString()); + return processVariablesIfPresent(tenant, namespace, data.replaceAll("\\$\\{" + key + "\\}", + propertyValue == null ? "" : propertyValue.replace("\\", "\\\\"))); + } + } else { + return data; + } + } + + /** + * Gets file contents. + * + * @param path the path + * @return the file contents + */ + public static String getFileContents(String path) { + try { + if (path != null) { + return IOUtils.toString(new URL(path)); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + return null; + } + + /** + * Gets file contents. + * + * @param path the path + * @return the file contents + */ + public static String getFileContents(Path path) { + try { + if (path != null) { + return new String(Files.readAllBytes(path)); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + return null; + } + + /** + * Gets concrete collection. + * + * @param clazz the clazz + * @return the concrete collection + */ + public static Collection getConcreteCollection(Class clazz) { + switch (clazz.getName()) { + case "java.util.Collection": + case "java.util.List": + return new ArrayList<>(); + case "java.util.Set": + return new HashSet<>(); + case "java.util.SortedSet": + return new TreeSet<>(); + case "java.util.Queue": + return new ConcurrentLinkedQueue<>(); + case "java.util.Deque": + return new ArrayDeque<>(); + case "java.util.concurrent.TransferQueue": + return new LinkedTransferQueue<>(); + case "java.util.concurrent.BlockingQueue": + return new LinkedBlockingQueue<>(); + default: + return null; + } + } + + /** + * Gets default for. + * + * @param clazz the clazz + * @return the default for + */ + public static Object getDefaultFor(Class clazz) { + if (byte.class == clazz) { + return new Byte("0"); + } else if (short.class == clazz) { + return new Short("0"); + } else if (int.class == clazz) { + return new Integer("0"); + } else if (float.class == clazz) { + return new Float("0"); + } else if (long.class == clazz) { + return new Long("0"); + } else if (double.class == clazz) { + return new Double("0"); + } else if (boolean.class == clazz) { + return Boolean.FALSE; + } + return new Character((char) 0); + } + + /** + * Gets compatible collection for abstract def. + * + * @param clazz the clazz + * @return the compatible collection for abstract def + */ + public static Collection getCompatibleCollectionForAbstractDef(Class clazz) { + if (BlockingQueue.class.isAssignableFrom(clazz)) { + return getConcreteCollection(BlockingQueue.class); + } + if (TransferQueue.class.isAssignableFrom(clazz)) { + return getConcreteCollection(TransferQueue.class); + } + if (Deque.class.isAssignableFrom(clazz)) { + return getConcreteCollection(Deque.class); + } + if (Queue.class.isAssignableFrom(clazz)) { + return getConcreteCollection(Queue.class); + } + if (SortedSet.class.isAssignableFrom(clazz)) { + return getConcreteCollection(SortedSet.class); + } + if (Set.class.isAssignableFrom(clazz)) { + return getConcreteCollection(Set.class); + } + if (List.class.isAssignableFrom(clazz)) { + return getConcreteCollection(List.class); + } + return null; + } + + /** + * Gets configuration repository key. + * + * @param array the array + * @return the configuration repository key + */ + public static String getConfigurationRepositoryKey(String[] array) { + Deque<String> stack = new ArrayDeque<>(); + stack.push(Constants.DEFAULT_TENANT); + for (String element : array) { + stack.push(element); + } + String toReturn = stack.pop(); + return stack.pop() + Constants.KEY_ELEMENTS_DELEMETER + toReturn; + } + + /** + * Gets configuration repository key. + * + * @param file the file + * @return the configuration repository key + */ + public static String getConfigurationRepositoryKey(File file) { + return getConfigurationRepositoryKey( + ConfigurationUtils.getNamespace(file).split(Constants.TENANT_NAMESPACE_SAPERATOR)); + } + + /** + * Gets configuration repository key. + * + * @param url the url + * @return the configuration repository key + */ + public static String getConfigurationRepositoryKey(URL url) { + return getConfigurationRepositoryKey( + ConfigurationUtils.getNamespace(url).split(Constants.TENANT_NAMESPACE_SAPERATOR)); + } + + /** + * To map linked hash map. + * + * @param config the config + * @return the linked hash map + */ + public static LinkedHashMap toMap(Configuration config) { + Iterator<String> iterator = config.getKeys(); + LinkedHashMap<String, String> map = new LinkedHashMap<>(); + while (iterator.hasNext()) { + String key = iterator.next(); + if (!(key.equals(Constants.MODE_KEY) || key.equals(Constants.NAMESPACE_KEY) + || key.equals(Constants.LOAD_ORDER_KEY))) { + map.put(key, config.getProperty(key).toString()); + } + } + + return map; + } + + /** + * Diff map. + * + * @param orig the orig + * @param latest the latest + * @return the map + */ + public static Map diff(LinkedHashMap orig, LinkedHashMap latest) { + orig = new LinkedHashMap<>(orig); + latest = new LinkedHashMap<>(latest); + List<String> set = new ArrayList(orig.keySet()); + for (String key : set) { + if (latest.remove(key, orig.get(key))) { + orig.remove(key); + } + } + Set<String> keys = latest.keySet(); + for (String key : keys) { + orig.remove(key); + } + set = new ArrayList(orig.keySet()); + for (String key : set) { + latest.put(key, ""); + } + return new HashMap<>(latest); + } + + /** + * Is array boolean. + * + * @param tenant the tenant + * @param namespace the namespace + * @param key the key + * @param processingHints the processing hints + * @return the boolean + * @throws Exception the exception + */ + public static boolean isArray(String tenant, String namespace, String key, int processingHints) + throws Exception { + Object obj = ConfigurationUtils + .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace), key, + processingHints); + return (obj == null) ? false : ConfigurationUtils.isCollection(obj.toString()); + } + + /** + * Is direct lookup boolean. + * + * @param hints the hints + * @return the boolean + */ + public static boolean isDirectLookup(int hints) { + return (hints & LATEST_LOOKUP.value()) == LATEST_LOOKUP.value(); + } + + /** + * Is external lookup boolean. + * + * @param hints the hints + * @return the boolean + */ + public static boolean isExternalLookup(int hints) { + return (hints & EXTERNAL_LOOKUP.value()) == EXTERNAL_LOOKUP.value(); + } + + /** + * Is node specific boolean. + * + * @param hints the hints + * @return the boolean + */ + public static boolean isNodeSpecific(int hints) { + return (hints & NODE_SPECIFIC.value()) == NODE_SPECIFIC.value(); + } + + public static boolean isZeroLengthArray(Class clazz, Object obj) { + if (clazz.isArray() && clazz.getComponentType().isPrimitive()) { + if (clazz.getComponentType() == int.class) { + return ((int[]) obj).length == 0; + } else if (clazz.getComponentType() == byte.class) { + return ((byte[]) obj).length == 0; + } else if (clazz.getComponentType() == short.class) { + return ((short[]) obj).length == 0; + } else if (clazz.getComponentType() == float.class) { + return ((float[]) obj).length == 0; + } else if (clazz.getComponentType() == boolean.class) { + return ((boolean[]) obj).length == 0; + } else if (clazz.getComponentType() == double.class) { + return ((double[]) obj).length == 0; + } else if (clazz.getComponentType() == long.class) { + return ((long[]) obj).length == 0; + } else { + return ((Object[]) obj).length == 0; + } + } + + return false; + } + + /** + * Checks if value is blank + * + * @param value + * @return + */ + public static boolean isBlank(String value) { + return value == null || value.trim().length() == 0; + } +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/Constants.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/Constants.java new file mode 100644 index 0000000000..a16607cbc0 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/Constants.java @@ -0,0 +1,14 @@ +package org.onap.config; + +public class Constants { + + public static final String DEFAULT_TENANT = "GLOBAL"; + public static final String DEFAULT_NAMESPACE = "COMMON"; + public static final String DB_NAMESPACE = "SYSTEM"; + public static final String KEY_ELEMENTS_DELEMETER = "-"; + public static final String TENANT_NAMESPACE_SAPERATOR = ":"; + public static final String NAMESPACE_KEY = "_config.namespace"; + public static final String MODE_KEY = "_config.mergeStrategy"; + public static final String MBEAN_NAME = "org.openecomp.jmx:name=SystemConfig"; + public final static String LOAD_ORDER_KEY="_config.loadOrder"; +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/NonConfigResource.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/NonConfigResource.java new file mode 100644 index 0000000000..830cdfef5a --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/NonConfigResource.java @@ -0,0 +1,95 @@ +package org.onap.config; + +import java.io.File; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; + +/** + * The type Non config resource. + */ +public class NonConfigResource { + + private static Set<URL> urls = new HashSet<>(); + private static Set<File> files = new HashSet<>(); + + /** + * Add. + * + * @param url the url + */ + public static void add(URL url) { + urls.add(url); + } + + /** + * Add. + * + * @param file the file + */ + public static void add(File file) { + files.add(file); + } + + /** + * Locate path. + * + * @param resource the resource + * @return the path + */ + public static Path locate(String resource) { + try { + if (resource != null) { + File file = new File(resource); + if (file.exists()) { + return Paths.get(resource); + } + for (File availableFile : files) { + if (availableFile.getAbsolutePath().endsWith(resource) && availableFile.exists()) { + return Paths.get(availableFile.getAbsolutePath()); + } + } + if (System.getProperty("node.config.location") != null) { + Path path = locate(new File(System.getProperty("node.config.location")), resource); + if (path != null) { + return path; + } + } + if (System.getProperty("config.location") != null) { + Path path = locate(new File(System.getProperty("config.location")), resource); + if (path != null) { + return path; + } + } + for (URL url : urls) { + if (url.getFile().endsWith(resource)) { + return Paths.get(url.toURI()); + } + } + } + } catch (Exception exception) { + exception.printStackTrace(); + } + return null; + } + + private static Path locate(File root, String resource) { + if (root.exists()) { + Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false); + Predicate<File> f1 = ConfigurationUtils::isConfig; + for (File file : filesystemResources) { + if (!f1.test(file)) { + add(file); + if (file.getAbsolutePath().endsWith(resource)) { + return Paths.get(file.getAbsolutePath()); + } + } + } + } + return null; + } +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/AgglomerateConfiguration.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/AgglomerateConfiguration.java new file mode 100644 index 0000000000..0934608c93 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/AgglomerateConfiguration.java @@ -0,0 +1,33 @@ +package org.onap.config.impl; + +import org.apache.commons.configuration2.DatabaseConfiguration; + +import java.util.Collections; +import java.util.Map; +import java.util.WeakHashMap; + +/** + * The type Agglomerate configuration. + */ +public class AgglomerateConfiguration extends DatabaseConfiguration { + + private final Map<String, Object> store = + Collections.synchronizedMap(new WeakHashMap<String, Object>()); + + /** + * Gets property value. + * + * @param key the key + * @return the property value + */ + public Object getPropertyValue(String key) { + Object objToReturn; + objToReturn = store.get(key); + if (objToReturn == null && !store.containsKey(key)) { + objToReturn = super.getProperty(key); + store.put(key, objToReturn); + } + return objToReturn; + } + +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/AggregateConfiguration.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/AggregateConfiguration.java new file mode 100644 index 0000000000..c8d76d9bd9 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/AggregateConfiguration.java @@ -0,0 +1,172 @@ +package org.onap.config.impl; + +import org.apache.commons.configuration2.CombinedConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.tree.MergeCombiner; +import org.apache.commons.configuration2.tree.OverrideCombiner; +import org.apache.commons.configuration2.tree.UnionCombiner; +import static org.onap.config.Constants.LOAD_ORDER_KEY; +import org.onap.config.ConfigurationUtils; +import org.onap.config.type.ConfigurationMode; + +import java.io.File; +import java.net.URL; +import java.util.HashMap; +import java.util.*; + +/** + * The type Aggregate configuration. + */ +public final class AggregateConfiguration { + + private Map<String, Configuration> rootConfig = new HashMap<>(); + private Map<String, Configuration> unionConfig = new HashMap<>(); + private Map<String, Configuration> mergeConfig = new HashMap<>(); + private Map<String, Configuration> overrideConfig = new LinkedHashMap<>(); + + /** + * Instantiates a new Aggregate configuration. + */ + public AggregateConfiguration() { + try { + Class clazz = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()); + if (!clazz.getCanonicalName() + .equals(ConfigurationImpl.class.getCanonicalName())) { + throw new RuntimeException("Illegal access."); + } + } catch (ClassNotFoundException cfe) { + throw new RuntimeException("Class not found while loading change notifier"); + } + } + + private void addConfig(String path, ConfigurationMode configMode, Configuration config) { + if (configMode != null) { + switch (configMode) { + case MERGE: + mergeConfig.put(path, config); + break; + case OVERRIDE: + overrideConfig.put(path, config); + break; + case UNION: + unionConfig.put(path, config); + break; + default: + } + } else { + rootConfig.put(path, config); + } + } + + /** + * Add config. + * + * @param file the file + * @throws Exception the exception + */ + public void addConfig(File file) throws Exception { + addConfig(file.getAbsolutePath().toUpperCase(), ConfigurationUtils.getMergeStrategy(file), + ConfigurationUtils.getConfigurationBuilder(file, false).getConfiguration()); + } + + /** + * Add config. + * + * @param url the url + * @throws Exception the exception + */ + public void addConfig(URL url) throws Exception { + addConfig(url.getFile().toUpperCase(), ConfigurationUtils.getMergeStrategy(url), + ConfigurationUtils.getConfigurationBuilder(url).getConfiguration()); + } + + /** + * Remove config. + * + * @param file the file + */ + public void removeConfig(File file) { + String key = file.getAbsolutePath().toUpperCase(); + if (rootConfig.containsKey(key)) { + rootConfig.remove(key); + } else if (mergeConfig.containsKey(key)) { + mergeConfig.remove(key); + } else if (unionConfig.containsKey(key)) { + unionConfig.remove(key); + } else if (overrideConfig.containsKey(key)) { + overrideConfig.remove(key); + } + } + + /** + * Contains config boolean. + * + * @param file the file + * @return the boolean + */ + public boolean containsConfig(File file) { + String key = file.getAbsolutePath().toUpperCase(); + return rootConfig.containsKey(key) || mergeConfig.containsKey(key) + || unionConfig.containsKey(key) || overrideConfig.containsKey(key); + } + + /** + * Gets final configuration. + * + * @return the final configuration + */ + public Configuration getFinalConfiguration() { + CombinedConfiguration ccRoot = new CombinedConfiguration(new MergeCombiner()); + ArrayList<Configuration> tempList = new ArrayList<>(rootConfig.values()); + Collections.sort(tempList, this::sortForMerge); + for (Configuration conf : tempList) { + ccRoot.addConfiguration(conf); + } + CombinedConfiguration ccMergeRoot = new CombinedConfiguration(new MergeCombiner()); + ccMergeRoot.addConfiguration(ccRoot); + tempList = new ArrayList<>(mergeConfig.values()); + Collections.sort(tempList, this::sortForMerge); + for (Configuration conf : tempList) { + ccMergeRoot.addConfiguration(conf); + } + CombinedConfiguration ccUnionRoot = new CombinedConfiguration(new UnionCombiner()); + ccUnionRoot.addConfiguration(ccMergeRoot); + for (Configuration conf : unionConfig.values()) { + ccUnionRoot.addConfiguration(conf); + } + ArrayList<Configuration> tempOverrideConfigs = new ArrayList<>(overrideConfig.values()); + Collections.reverse(tempOverrideConfigs); + Collections.sort(tempOverrideConfigs, this::sortForOverride); + CombinedConfiguration ccOverrideRoot = new CombinedConfiguration(new OverrideCombiner()); + for (Configuration conf : tempOverrideConfigs) { + ccOverrideRoot.addConfiguration(conf); + } + ccOverrideRoot.addConfiguration(ccUnionRoot); + return ccOverrideRoot; + } + + private int sortForOverride(Configuration conf1, Configuration conf2){ + String order1 = conf1.getString(LOAD_ORDER_KEY); + String order2 = conf2.getString(LOAD_ORDER_KEY); + if (ConfigurationUtils.isBlank(order1) || !order1.trim().matches("\\d+")){ + order1 = "0"; + } + if (ConfigurationUtils.isBlank(order2) || !order2.trim().matches("\\d+")){ + order2 = "0"; + } + return Integer.parseInt(order2.trim())-Integer.parseInt(order1.trim()); + } + + private int sortForMerge(Configuration conf1, Configuration conf2){ + String order1 = conf1.getString(LOAD_ORDER_KEY); + String order2 = conf2.getString(LOAD_ORDER_KEY); + if (ConfigurationUtils.isBlank(order1) || !order1.trim().matches("\\d+")){ + order1 = "0"; + } + if (ConfigurationUtils.isBlank(order2) || !order2.trim().matches("\\d+")){ + order2 = "0"; + } + return Integer.parseInt(order1.trim())-Integer.parseInt(order2.trim()); + } + +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/CliConfigurationImpl.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/CliConfigurationImpl.java new file mode 100644 index 0000000000..3bdebffb48 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/CliConfigurationImpl.java @@ -0,0 +1,354 @@ +package org.onap.config.impl; + +import static org.onap.config.Constants.DB_NAMESPACE; +import static org.onap.config.Constants.DEFAULT_NAMESPACE; +import static org.onap.config.Constants.DEFAULT_TENANT; +import static org.onap.config.Constants.KEY_ELEMENTS_DELEMETER; +import static org.onap.config.Constants.LOAD_ORDER_KEY; +import static org.onap.config.Constants.MBEAN_NAME; +import static org.onap.config.Constants.MODE_KEY; +import static org.onap.config.Constants.NAMESPACE_KEY; + +import org.apache.commons.configuration2.CombinedConfiguration; +import org.apache.commons.configuration2.CompositeConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.FileBasedConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.onap.config.type.ConfigurationQuery; +import org.onap.config.ConfigurationUtils; +import org.onap.config.Constants; +import org.onap.config.api.ConfigurationManager; +import org.onap.config.api.Hint; +import org.onap.config.type.ConfigurationUpdate; + +import java.io.File; +import java.io.PrintWriter; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.management.MBeanServer; +import javax.management.MBeanServerDelegate; +import javax.management.MBeanServerNotification; +import javax.management.Notification; +import javax.management.ObjectName; +import javax.management.StandardMBean; + +/** + * The type Cli configuration. + */ +public final class CliConfigurationImpl extends ConfigurationImpl implements ConfigurationManager { + + /** + * Instantiates a new Cli configuration. + * + * @throws Exception the exception + */ + public CliConfigurationImpl() throws Exception { + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName name = new ObjectName(MBEAN_NAME); + if (mbs.isRegistered(name)) { + mbs.unregisterMBean(name); + } + mbs.registerMBean(new StandardMBean(this, ConfigurationManager.class), name); + //mbs.registerMBean(getMBean(), name); + mbs.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, this::handleNotification, null, + null); + //mbs.addNotificationListener(name, this::handleNotification, null, null); + } + + + /** + * Handle notification. + * + * @param notification the notification + * @param handback the handback + */ + public void handleNotification(Notification notification, Object handback) { + if (notification instanceof MBeanServerNotification) { + MBeanServerNotification mbs = (MBeanServerNotification) notification; + if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(mbs.getType())) { + try { + String mbean = + ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE) + .getString("shutdown.mbean"); + if (mbs.getMBeanName() + .equals(mbean == null ? new ObjectName(MBEAN_NAME) : new ObjectName(mbean))) { + changeNotifier.shutdown(); + ConfigurationDataSource.lookup().close(); + } + } catch (Exception exception) { + //do nothing. + } + } else if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(mbs.getType())) { + mbs.getMBeanName(); + } + } + } + + public String getConfigurationValue(Map<String, Object> input) { + return getConfigurationValue((ConfigurationQuery) getInput(input)); + } + + private String getConfigurationValue(ConfigurationQuery queryData) { + try { + if (queryData.isFallback()) { + return ConfigurationUtils.getCommaSeparatedList( + get(queryData.getTenant(), queryData.getNamespace(), queryData.getKey(), String[].class, + queryData.isLatest() ? Hint.LATEST_LOOKUP : Hint.DEFAULT, + queryData.isExternalLookup() ? Hint.EXTERNAL_LOOKUP : Hint.DEFAULT, + queryData.isNodeSpecific() ? Hint.NODE_SPECIFIC : Hint.DEFAULT)); + } else { + String[] list = + getInternal(queryData.getTenant(), queryData.getNamespace(), queryData.getKey(), + String[].class, queryData.isLatest() ? Hint.LATEST_LOOKUP : Hint.DEFAULT, + queryData.isExternalLookup() ? Hint.EXTERNAL_LOOKUP : Hint.DEFAULT, + queryData.isNodeSpecific() ? Hint.NODE_SPECIFIC : Hint.DEFAULT); + return ConfigurationUtils + .getCommaSeparatedList(list == null ? Arrays.asList() : Arrays.asList(list)); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + return null; + } + + public void updateConfigurationValue(Map<String, Object> input) { + updateConfigurationValue((ConfigurationUpdate) getInput(input)); + } + + private void updateConfigurationValue(ConfigurationUpdate updateData) { + + try { + if (!ConfigurationRepository.lookup().isValidTenant(updateData.getTenant())) { + throw new RuntimeException("Invalid tenantId."); + } + if (!ConfigurationRepository.lookup().isValidNamespace(updateData.getNamespace())) { + throw new RuntimeException("Invalid Namespace."); + } + } catch (NullPointerException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + try { + boolean keyPresent = + isKeyExists(updateData.getTenant(), updateData.getNamespace(), updateData.getKey()); + if (keyPresent) { + boolean isUpdated = false; + Object[] paramArray = new Object[]{ + updateData.getTenant() + KEY_ELEMENTS_DELEMETER + updateData.getNamespace(), + new Long(System.currentTimeMillis()), updateData.getKey(), + getConfigurationValue(updateData), updateData.getValue()}; + Configuration config = ConfigurationRepository.lookup() + .getConfigurationFor(updateData.getTenant(), updateData.getNamespace()); + if (config instanceof AgglomerateConfiguration || config instanceof CombinedConfiguration) { + CompositeConfiguration cc = new CompositeConfiguration(); + cc.addConfiguration(config); + config = cc; + } + CompositeConfiguration configuration = (CompositeConfiguration) config; + int overrideIndex = -1; + for (int i = 0; i < configuration.getNumberOfConfigurations(); i++) { + if (!updateData.isNodeOverride() + && (configuration.getConfiguration(i) instanceof AgglomerateConfiguration + || configuration.getConfiguration(i) instanceof CombinedConfiguration)) { + configuration.getConfiguration(i) + .setProperty(updateData.getKey(), updateData.getValue()); + isUpdated = true; + break; + } else if (updateData.isNodeOverride() + && configuration.getConfiguration(i) instanceof FileBasedConfiguration) { + configuration.getConfiguration(i) + .setProperty(updateData.getKey(), updateData.getValue()); + isUpdated = true; + overrideIndex = i; + break; + } + } + if (!isUpdated) { + if (updateData.isNodeOverride()) { + PropertiesConfiguration pc = new PropertiesConfiguration(); + pc.setProperty(NAMESPACE_KEY, + updateData.getTenant() + Constants.TENANT_NAMESPACE_SAPERATOR + + updateData.getNamespace()); + pc.setProperty(MODE_KEY, "OVERRIDE"); + pc.setProperty(updateData.getKey(), updateData.getValue()); + if (System.getProperty("node.config.location") != null + && System.getProperty("node.config.location").trim().length() > 0) { + File file = new File(System.getProperty("node.config.location"), + updateData.getTenant() + File.separator + updateData.getNamespace() + + File.separator + "config.properties"); + file.getParentFile().mkdirs(); + PrintWriter out = new PrintWriter(file); + pc.write(out); + out.close(); + ConfigurationRepository.lookup().populateOverrideConfigurtaion( + updateData.getTenant() + KEY_ELEMENTS_DELEMETER + updateData.getNamespace(), + file); + } + } else { + configuration.getConfiguration(0) + .setProperty(updateData.getKey(), updateData.getValue()); + } + } + if (!updateData.isNodeOverride()) { + ConfigurationUtils.executeInsertSql( + ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE) + .getString("insertconfigurationchangecql"), paramArray); + } else { + ConfigurationRepository.lookup().refreshOverrideConfigurtaionFor( + updateData.getTenant() + KEY_ELEMENTS_DELEMETER + updateData.getNamespace(), + overrideIndex); + } + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + private boolean isKeyExists(String tenant, String namespace, String key) { + boolean keyExist = false; + try { + keyExist = + ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace).containsKey(key); + if (!keyExist && !DEFAULT_TENANT.equals(tenant)) { + keyExist = ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, namespace) + .containsKey(key); + } + if (!keyExist && !DEFAULT_NAMESPACE.equals(namespace)) { + keyExist = ConfigurationRepository.lookup().getConfigurationFor(tenant, DEFAULT_NAMESPACE) + .containsKey(key); + } + if (!keyExist && !DEFAULT_TENANT.equals(tenant) && !DEFAULT_NAMESPACE.equals(namespace)) { + keyExist = + ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DEFAULT_NAMESPACE) + .containsKey(key); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + return keyExist; + } + + public Map<String, String> listConfiguration(Map<String, Object> input) { + return listConfiguration((ConfigurationQuery) getInput(input)); + } + + private Map<String, String> listConfiguration(ConfigurationQuery query) { + Map<String, String> map = new HashMap<>(); + try { + Collection<String> keys = getKeys(query.getTenant(), query.getNamespace()); + for (String key : keys) { + map.put(key, getConfigurationValue(query.key(key))); + } + } catch (Exception exception) { + exception.printStackTrace(); + return null; + } + return map; + } + + @Override + public boolean updateConfigurationValues(String tenant, String namespace, + Map configKeyValueStore) { + boolean valueToReturn = true; + Iterator<String> keys = configKeyValueStore.keySet().iterator(); + while (keys.hasNext()) { + try { + String key = keys.next(); + ConfigurationUpdate updateData = new ConfigurationUpdate(); + updateData.tenant(tenant).namespace(namespace).key(key); + updateData.value(configKeyValueStore.get(key).toString()); + updateConfigurationValue(updateData); + } catch (Exception exception) { + exception.printStackTrace(); + valueToReturn = false; + } + } + return valueToReturn; + } + + private Object getInput(Map<String, Object> input) { + Object toReturn = null; + try { + toReturn = Class.forName(input.get("ImplClass").toString()).newInstance(); + Method[] methods = toReturn.getClass().getMethods(); + for (Method method : methods) { + if (input.containsKey(method.getName())) { + method.invoke(toReturn, input.get(method.getName())); + } + } + } catch (Exception exception) { + exception.printStackTrace(); + } + + return toReturn; + } + + @Override + public Collection<String> getTenants() { + return ConfigurationRepository.lookup().getTenants(); + } + + @Override + public Collection<String> getNamespaces() { + return ConfigurationRepository.lookup().getNamespaces(); + } + + private ArrayList<String> getInMemoryKeys(String tenant, String namespace) { + ArrayList<String> keys = new ArrayList<>(); + + try { + Iterator<String> iter = + ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace).getKeys(); + while (iter.hasNext()) { + String key = iter.next(); + if (!(key.equals(NAMESPACE_KEY) || key.equals(MODE_KEY) + || key.equals(LOAD_ORDER_KEY))) { + keys.add(key); + } + } + } catch (Exception exception) { + //do nothing + } + + return keys; + } + + @Override + public Collection<String> getKeys(String tenant, String namespace) { + Set<String> keyCollection = new HashSet<>(); + try { + keyCollection.addAll(ConfigurationUtils.executeSelectSql( + ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE) + .getString("fetchkeysql"), + new String[]{tenant + KEY_ELEMENTS_DELEMETER + DEFAULT_NAMESPACE})); + keyCollection.addAll(ConfigurationUtils.executeSelectSql( + ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE) + .getString("fetchkeysql"), + new String[]{tenant + KEY_ELEMENTS_DELEMETER + namespace})); + keyCollection.addAll(ConfigurationUtils.executeSelectSql( + ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE) + .getString("fetchkeysql"), + new String[]{DEFAULT_TENANT + KEY_ELEMENTS_DELEMETER + namespace})); + keyCollection.addAll(ConfigurationUtils.executeSelectSql( + ConfigurationRepository.lookup().getConfigurationFor(DEFAULT_TENANT, DB_NAMESPACE) + .getString("fetchkeysql"), + new String[]{DEFAULT_TENANT + KEY_ELEMENTS_DELEMETER + DEFAULT_NAMESPACE})); + } catch (Exception exception) { + exception.printStackTrace(); + keyCollection.addAll(getInMemoryKeys(tenant, DEFAULT_NAMESPACE)); + keyCollection.addAll(getInMemoryKeys(tenant, namespace)); + keyCollection.addAll(getInMemoryKeys(DEFAULT_TENANT, namespace)); + keyCollection.addAll(getInMemoryKeys(DEFAULT_TENANT, DEFAULT_NAMESPACE)); + } + return keyCollection; + } +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationChangeNotifier.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationChangeNotifier.java new file mode 100644 index 0000000000..a7c10caae9 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationChangeNotifier.java @@ -0,0 +1,474 @@ +package org.onap.config.impl; + +import org.onap.config.ConfigurationUtils; +import org.onap.config.Constants; +import org.onap.config.api.ConfigurationChangeListener; +import org.onap.config.api.ConfigurationManager; +import org.onap.config.api.Hint; + +import java.io.File; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Method; +import java.nio.file.ClosedWatchServiceException; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.Vector; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.management.JMX; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; + + +/** + * The type Configuration change notifier. + */ +public final class ConfigurationChangeNotifier { + + private final HashMap<String, List<NotificationData>> store = new HashMap<>(); + private final ScheduledExecutorService executor = + Executors.newScheduledThreadPool(5, ConfigurationUtils.getThreadFactory()); + private final ExecutorService notificationExecutor = + Executors.newCachedThreadPool(ConfigurationUtils.getThreadFactory()); + private final Map<String, WatchService> watchServiceCollection = + Collections.synchronizedMap(new HashMap<>()); + + static { + if (!Thread.currentThread().getStackTrace()[2].getClassName() + .equals(ConfigurationImpl.class.getName())) { + throw new RuntimeException("Illegal access."); + } + } + + /** + * Instantiates a new Configuration change notifier. + * + * @param inMemoryConfig the in memory config + */ + public ConfigurationChangeNotifier(Map<String, AggregateConfiguration> inMemoryConfig) { + executor.scheduleWithFixedDelay(() -> this + .pollFilesystemAndUpdateConfigurationIfRequired(inMemoryConfig, + System.getProperty("config.location"), false), 1, 1, TimeUnit.MILLISECONDS); + executor.scheduleWithFixedDelay(() -> this + .pollFilesystemAndUpdateConfigurationIfRequired(inMemoryConfig, + System.getProperty("tenant.config.location"), true), 1, 1, TimeUnit.MILLISECONDS); + executor.scheduleWithFixedDelay(() -> this + .pollFilesystemAndUpdateNodeSpecificConfigurationIfRequired( + System.getProperty("node.config.location")), 1, 1, TimeUnit.MILLISECONDS); + } + + /** + * Shutdown. + */ + public void shutdown() { + for (WatchService watch : watchServiceCollection.values()) { + try { + watch.close(); + } catch (IOException exception) { + //do nothing + } + } + executor.shutdownNow(); + } + + /** + * Poll filesystem and update configuration if required. + * + * @param inMemoryConfig the in memory config + * @param location the location + * @param isTenantLocation the is tenant location + */ + public void pollFilesystemAndUpdateConfigurationIfRequired( + Map<String, AggregateConfiguration> inMemoryConfig, String location, + boolean isTenantLocation) { + try { + Set<Path> paths = watchForChange(location); + if (paths != null) { + for (Path path : paths) { + File file = path.toAbsolutePath().toFile(); + String repositoryKey = null; + if (ConfigurationUtils.isConfig(file) && file.isFile()) { + if (isTenantLocation) { + Collection<File> tenantsRoot = + ConfigurationUtils.getAllFiles(new File(location), false, true); + for (File tenantRoot : tenantsRoot) { + if (file.getAbsolutePath().startsWith(tenantRoot.getAbsolutePath())) { + repositoryKey = ConfigurationUtils.getConfigurationRepositoryKey( + (tenantRoot.getName() + Constants.TENANT_NAMESPACE_SAPERATOR + + ConfigurationUtils.getNamespace(file)) + .split(Constants.TENANT_NAMESPACE_SAPERATOR)); + } + } + } else { + repositoryKey = ConfigurationUtils.getConfigurationRepositoryKey(file); + } + AggregateConfiguration config = inMemoryConfig.get(repositoryKey); + if (config != null) { + LinkedHashMap origConfig = ConfigurationUtils.toMap(config.getFinalConfiguration()); + config.addConfig(file); + LinkedHashMap latestConfig = ConfigurationUtils.toMap(config.getFinalConfiguration()); + Map map = ConfigurationUtils.diff(origConfig, latestConfig); + String[] tenantNamespaceArray = + repositoryKey.split(Constants.KEY_ELEMENTS_DELEMETER); + updateConfigurationValues(tenantNamespaceArray[0], tenantNamespaceArray[1], map); + } + } else { + for (String configKey : inMemoryConfig.keySet()) { + repositoryKey = configKey; + AggregateConfiguration config = inMemoryConfig.get(repositoryKey); + if (config.containsConfig(file)) { + LinkedHashMap origConfig = ConfigurationUtils.toMap(config.getFinalConfiguration()); + config.removeConfig(file); + LinkedHashMap latestConfig = + ConfigurationUtils.toMap(config.getFinalConfiguration()); + Map map = ConfigurationUtils.diff(origConfig, latestConfig); + String[] tenantNamespaceArray = + repositoryKey.split(Constants.KEY_ELEMENTS_DELEMETER); + updateConfigurationValues(tenantNamespaceArray[0], tenantNamespaceArray[1], + map); + } + } + } + } + } + } catch (ClosedWatchServiceException exception) { + // do nothing. + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + private void updateConfigurationValues(String tenant, String namespace, Map map) + throws Exception { + MBeanServerConnection mbsc = ManagementFactory.getPlatformMBeanServer(); + ObjectName mbeanName = new ObjectName(Constants.MBEAN_NAME); + ConfigurationManager conf = + JMX.newMBeanProxy(mbsc, mbeanName, ConfigurationManager.class, + true); + conf.updateConfigurationValues(tenant, namespace, map); + } + + /** + * Poll filesystem and update node specific configuration if required. + * + * @param location the location + */ + public void pollFilesystemAndUpdateNodeSpecificConfigurationIfRequired(String location) { + try { + Set<Path> paths = watchForChange(location); + if (paths != null) { + for (Path path : paths) { + File file = path.toAbsolutePath().toFile(); + + if (ConfigurationUtils.isConfig(file)) { + String repositoryKey = ConfigurationUtils.getConfigurationRepositoryKey(file); + ConfigurationRepository.lookup().populateOverrideConfigurtaion(repositoryKey, file); + } else { + ConfigurationRepository.lookup().removeOverrideConfigurtaion(file); + } + } + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + /** + * Notify changes towards. + * + * @param tenant the tenant + * @param component the component + * @param key the key + * @param myself the myself + * @throws Exception the exception + */ + public void notifyChangesTowards(String tenant, String component, String key, + ConfigurationChangeListener myself) throws Exception { + List<NotificationData> notificationList = + store.get(tenant + Constants.KEY_ELEMENTS_DELEMETER + component); + if (notificationList == null) { + notificationList = Collections.synchronizedList(new ArrayList<NotificationData>()); + store.put(tenant + Constants.KEY_ELEMENTS_DELEMETER + component, notificationList); + executor.scheduleWithFixedDelay( + () -> triggerScanning(tenant + Constants.KEY_ELEMENTS_DELEMETER + component), 1, 30000, + TimeUnit.MILLISECONDS); + } + notificationList.add(new NotificationData(tenant, component, key, myself)); + } + + /** + * Stop notification towards. + * + * @param tenant the tenant + * @param component the component + * @param key the key + * @param myself the myself + * @throws Exception the exception + */ + public void stopNotificationTowards(String tenant, String component, String key, + ConfigurationChangeListener myself) throws Exception { + List<NotificationData> notificationList = + store.get(tenant + Constants.KEY_ELEMENTS_DELEMETER + component); + if (notificationList != null) { + boolean removed = + notificationList.remove(new NotificationData(tenant, component, key, myself)); + if (removed && notificationList.isEmpty()) { + store.remove(tenant + Constants.KEY_ELEMENTS_DELEMETER + component); + } + } + + } + + private void triggerScanning(String key) { + if (store.get(key) != null) { + notificationExecutor.submit(() -> scanForChanges(key)); + } else { + throw new IllegalArgumentException("Notification service for " + key + " is suspended."); + } + } + + private void scanForChanges(String key) { + List<NotificationData> list = store.get(key); + if (list != null) { + list.stream() + .filter(NotificationData::isChanged) + .forEach(notificationData -> notificationExecutor.submit(() -> sendNotification(notificationData))); + } + } + + private void sendNotification(NotificationData notificationData) { + try { + notificationData.dispatchNotification(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + private Set<Path> watchForChange(String location) throws Exception { + if (location == null || location.trim().length() == 0) { + return null; + } + File file = new File(location); + if (!file.exists()) { + return null; + } + Path path = file.toPath(); + Set<Path> toReturn = new HashSet<>(); + try (final WatchService watchService = FileSystems.getDefault().newWatchService()) { + watchServiceCollection.put(location, watchService); + path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY, + StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE); + for (File dir : ConfigurationUtils.getAllFiles(file, true, true)) { + dir.toPath().register(watchService, StandardWatchEventKinds.ENTRY_MODIFY, + StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE); + } + while (true) { + final WatchKey wk = watchService.take(); + Thread.sleep(ConfigurationRepository.lookup() + .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE) + .getLong("event.fetch.delay")); + for (WatchEvent<?> event : wk.pollEvents()) { + Object context = event.context(); + if (context instanceof Path) { + File newFile = new File(((Path) wk.watchable()).toFile(), context.toString()); + if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { + if (newFile.isDirectory()) { + newFile.toPath().register(watchService, StandardWatchEventKinds.ENTRY_MODIFY, + StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE); + continue; + } + } else if (event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) { + if (newFile.isDirectory()) { + continue; + } + } + toReturn.add(newFile.toPath()); + } + } + if (toReturn.isEmpty()) { + continue; + } + break; + } + } + return toReturn; + } + + /** + * The type Notification data. + */ + static class NotificationData { + + /** + * The Tenant. + */ + final String tenant; + /** + * The Namespace. + */ + final String namespace; + /** + * The Key. + */ + final String key; + /** + * The Myself. + */ + final ConfigurationChangeListener myself; + /** + * The Current value. + */ + Object currentValue; + /** + * The Is array. + */ + boolean isArray; + + /** + * Instantiates a new Notification data. + * + * @param tenant the tenant + * @param component the component + * @param key the key + * @param myself the myself + * @throws Exception the exception + */ + public NotificationData(String tenant, String component, String key, + ConfigurationChangeListener myself) throws Exception { + this.tenant = tenant; + this.namespace = component; + this.key = key; + this.myself = myself; + if (!ConfigurationRepository.lookup().getConfigurationFor(tenant, component) + .containsKey(key)) { + throw new RuntimeException("Key[" + key + "] not found."); + } + isArray = ConfigurationUtils.isArray(tenant, component, key, Hint.DEFAULT.value()); + if (isArray) { + currentValue = ConfigurationManager.lookup().getAsStringValues(tenant, component, key); + } else { + currentValue = ConfigurationManager.lookup().getAsString(tenant, component, key); + } + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof NotificationData)) { + return false; + } + NotificationData nd = (NotificationData) obj; + return Objects.equals(tenant, nd.tenant) + && Objects.equals(namespace, nd.namespace) + && Objects.equals(key, nd.key) + && Objects.equals(myself, nd.myself) + && Objects.equals(currentValue, nd.currentValue) // it's either String or List<String> + && isArray == nd.isArray; + } + + @Override + public int hashCode() { + return Objects.hash(tenant, namespace, key, myself, currentValue, isArray); + } + + /** + * Is changed boolean. + * + * @return the boolean + */ + public boolean isChanged() { + Object latestValue; + try { + if (isArray) { + latestValue = ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key); + } else { + latestValue = ConfigurationManager.lookup().getAsString(tenant, namespace, key); + } + if (!isArray) { + return !currentValue.equals(latestValue); + } else { + Collection<String> oldCollection = (Collection<String>) currentValue; + Collection<String> newCollection = (Collection<String>) latestValue; + for (String val : oldCollection) { + if (!newCollection.remove(val)) { + return true; + } + } + return !newCollection.isEmpty(); + } + } catch (Exception exception) { + return false; + } + } + + /** + * Dispatch notification. + * + * @throws Exception the exception + */ + public void dispatchNotification() throws Exception { + Method method = null; + Vector<Object> parameters = null; + try { + Object latestValue; + if (isArray) { + latestValue = ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key); + } else { + latestValue = ConfigurationManager.lookup().getAsString(tenant, namespace, key); + } + Method[] methods = myself.getClass().getDeclaredMethods(); + if (methods != null && methods.length > 0) { + method = methods[0]; + int paramCount = method.getParameterCount(); + parameters = new Vector<>(); + if (paramCount > 4) { + if (tenant.equals(Constants.DEFAULT_TENANT)) { + parameters.add(null); + } else { + parameters.add(tenant); + } + } + if (paramCount > 3) { + if (namespace.equals(Constants.DEFAULT_NAMESPACE)) { + parameters.add(null); + } else { + parameters.add(namespace); + } + } + parameters.add(key); + parameters.add(currentValue); + parameters.add(latestValue); + method.setAccessible(true); + } + } catch (Exception exception) { + exception.printStackTrace(); + } finally { + isArray = ConfigurationUtils.isArray(tenant, namespace, key, Hint.DEFAULT.value()); + if (isArray) { + currentValue = ConfigurationManager.lookup().getAsStringValues(tenant, namespace, key); + } else { + currentValue = ConfigurationManager.lookup().getAsString(tenant, namespace, key); + } + if (method != null && parameters != null) { + method.invoke(myself, parameters.toArray()); + } + } + } + } +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationDataSource.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationDataSource.java new file mode 100644 index 0000000000..ea9c61f635 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationDataSource.java @@ -0,0 +1,105 @@ +package org.onap.config.impl; + +import org.apache.commons.configuration2.ImmutableConfiguration; +import org.apache.commons.dbcp2.BasicDataSource; +import org.apache.commons.lang3.StringUtils; +import org.onap.config.ConfigurationUtils; +import org.onap.config.Constants; + +import java.sql.Driver; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.ServiceLoader; +import java.util.Set; + +/** + * The type Configuration data source. + */ +public final class ConfigurationDataSource { + + private static BasicDataSource configDBDatasource = null; + private static Set<String> validCallers = Collections.unmodifiableSet(new HashSet<>( + Arrays.asList(ConfigurationUtils.class.getName(), CliConfigurationImpl.class.getName()))); + + private ConfigurationDataSource() { + //Hide constructor to prevent instantiation using the default implicit constructor + } + + static { + try { + configDBDatasource = initDataSource(); + } catch (Exception exception) { + System.err.println("Datasource initialization error. Configuration management will be using" + + "in-memory persistence."); + } + } + + /** + * Lookup basic data source. + * + * @return the basic data source + * @throws Exception the exception + */ + public static BasicDataSource lookup() throws Exception { + if (validCallers.contains(Thread.currentThread().getStackTrace()[2].getClassName())) { + return configDBDatasource; + } else { + return null; + } + } + + /** + * Init data source basic data source. + * + * @return the basic data source + * @throws Exception the exception + */ + public static BasicDataSource initDataSource() throws Exception { + ImmutableConfiguration dbConfig = ConfigurationRepository.lookup() + .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE); + if (StringUtils.isEmpty(dbConfig.getString("dbhost"))) { + return null; + } + BasicDataSource datasource = new BasicDataSource(); + String driverClassName = dbConfig.getString("driverClassName"); + String jdbcUrl = dbConfig.getString("jdbcURL"); + if (!isDriverSuitable(driverClassName, jdbcUrl)) { + driverClassName = getDriverFor(jdbcUrl); + } + datasource.setDriverClassName(driverClassName); + datasource.setUrl(jdbcUrl); + String dbuser = dbConfig.getString("dbuser"); + String dbpassword = dbConfig.getString("dbpassword"); + if (dbuser != null && dbuser.trim().length() > 0) { + datasource.setUsername(dbuser); + } + if (dbpassword != null && dbpassword.trim().length() > 0) { + datasource.setPassword(dbpassword); + } + return datasource; + } + + private static boolean isDriverSuitable(String driverClassName, String url) { + if (driverClassName == null || driverClassName.trim().length() == 0) { + return false; + } + try { + Driver driver = Driver.class.cast(Class.forName(driverClassName).newInstance()); + return driver.acceptsURL(url); + } catch (Exception exception) { + return false; + } + } + + private static String getDriverFor(String url) throws Exception { + ServiceLoader<Driver> loader = ServiceLoader.load(Driver.class); + for (Driver driver : loader) { + if (driver.acceptsURL(url)) { + return driver.getClass().getName(); + } + } + throw new RuntimeException("No Suitable driver found for " + url); + } + +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationFilter.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationFilter.java new file mode 100644 index 0000000000..9df69ed1d7 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationFilter.java @@ -0,0 +1,39 @@ +package org.onap.config.impl; + +import org.onap.config.Constants; +import org.onap.config.api.Configuration; + +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; + +@WebFilter("/") +public class ConfigurationFilter implements Filter { + + @Override + public void init(FilterConfig paramFilterConfig) throws ServletException { + //Use the default behavior + } + + @Override + public void doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, + FilterChain paramFilterChain) throws IOException, ServletException { + Configuration.tenant.set(Constants.DEFAULT_TENANT); + try { + paramFilterChain.doFilter(paramServletRequest, paramServletResponse); + } finally { + Configuration.tenant.remove(); + } + } + + @Override + public void destroy() { + //Use the default behavior + } + +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationImpl.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationImpl.java new file mode 100644 index 0000000000..43b1b96fc5 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationImpl.java @@ -0,0 +1,679 @@ +package org.onap.config.impl; + +import static org.onap.config.ConfigurationUtils.getConfigurationRepositoryKey; + +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.DatabaseConfiguration; +import org.onap.config.ConfigurationUtils; +import org.onap.config.Constants; +import org.onap.config.NonConfigResource; +import org.onap.config.api.Config; +import org.onap.config.api.ConfigurationChangeListener; +import org.onap.config.api.Hint; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; + +/** + * The type Configuration. + */ +public class ConfigurationImpl implements org.onap.config.api.Configuration { + + private static ThreadLocal<String> tenant = new ThreadLocal<String>() { + protected String initialValue() { + return Constants.DEFAULT_TENANT; + } + + ; + }; + private static boolean instantiated = false; + /** + * The Change notifier. + */ + ConfigurationChangeNotifier changeNotifier; + + /** + * Instantiates a new Configuration. + * + * @throws Exception the exception + */ + public ConfigurationImpl() throws Exception { + if (instantiated || !CliConfigurationImpl.class.isAssignableFrom(this.getClass())) { + throw new RuntimeException("Illegal access to configuration."); + } + Map<String, AggregateConfiguration> moduleConfigStore = new HashMap<>(); + List<URL> classpathResources = ConfigurationUtils.getAllClassPathResources(); + Predicate<URL> predicate = ConfigurationUtils::isConfig; + for (URL url : classpathResources) { + if (predicate.test(url)) { + String moduleName = ConfigurationUtils.getConfigurationRepositoryKey(url); + AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName); + if (moduleConfig == null) { + moduleConfig = new AggregateConfiguration(); + moduleConfigStore.put(moduleName, moduleConfig); + } + moduleConfig.addConfig(url); + } else { + NonConfigResource.add(url); + } + } + String configLocation = System.getProperty("config.location"); + if (configLocation != null && configLocation.trim().length() > 0) { + File root = new File(configLocation); + Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false); + Predicate<File> filePredicate = ConfigurationUtils::isConfig; + for (File file : filesystemResources) { + if (filePredicate.test(file)) { + String moduleName = ConfigurationUtils.getConfigurationRepositoryKey(file); + AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName); + if (moduleConfig == null) { + moduleConfig = new AggregateConfiguration(); + moduleConfigStore.put(moduleName, moduleConfig); + } + moduleConfig.addConfig(file); + } else { + NonConfigResource.add(file); + } + } + } + String tenantConfigLocation = System.getProperty("tenant.config.location"); + if (tenantConfigLocation != null && tenantConfigLocation.trim().length() > 0) { + File root = new File(tenantConfigLocation); + Collection<File> tenantsRoot = ConfigurationUtils.getAllFiles(root, false, true); + Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false); + Predicate<File> filePredicate = ConfigurationUtils::isConfig; + for (File file : filesystemResources) { + if (filePredicate.test(file)) { + String moduleName = ConfigurationUtils.getNamespace(file); + for (File tenanatFileRoot : tenantsRoot) { + if (file.getAbsolutePath().startsWith(tenanatFileRoot.getAbsolutePath())) { + moduleName = ConfigurationUtils.getConfigurationRepositoryKey( + (tenanatFileRoot.getName().toUpperCase() + Constants.TENANT_NAMESPACE_SAPERATOR + + moduleName).split(Constants.TENANT_NAMESPACE_SAPERATOR)); + } + } + AggregateConfiguration moduleConfig = moduleConfigStore.get(moduleName); + if (moduleConfig == null) { + moduleConfig = new AggregateConfiguration(); + moduleConfigStore.put(moduleName, moduleConfig); + } + moduleConfig.addConfig(file); + } + } + } + populateFinalConfigurationIncrementally(moduleConfigStore); + ConfigurationRepository.lookup().initTenantsAndNamespaces(); + String nodeConfigLocation = System.getProperty("node.config.location"); + if (nodeConfigLocation != null && nodeConfigLocation.trim().length() > 0) { + File root = new File(nodeConfigLocation); + Collection<File> filesystemResources = ConfigurationUtils.getAllFiles(root, true, false); + Predicate<File> filePredicate = ConfigurationUtils::isConfig; + for (File file : filesystemResources) { + if (filePredicate.test(file)) { + ConfigurationRepository.lookup().populateOverrideConfigurtaion( + ConfigurationUtils.getConfigurationRepositoryKey(ConfigurationUtils.getNamespace(file) + .split(Constants.TENANT_NAMESPACE_SAPERATOR)), file); + } + } + } + instantiated = true; + changeNotifier = new ConfigurationChangeNotifier(moduleConfigStore); + } + + @Override + public void addConfigurationChangeListener(String tenant, String namespace, String key, + ConfigurationChangeListener myself) { + tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase() + : Constants.DEFAULT_TENANT; + namespace = + ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase() + : Constants.DEFAULT_NAMESPACE; + if (key == null || key.trim().length() == 0) { + throw new IllegalArgumentException("Key can't be null."); + } + if (myself == null) { + throw new IllegalArgumentException("ConfigurationChangeListener instance is null."); + } + try { + changeNotifier.notifyChangesTowards(tenant, namespace, key, myself); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + private void populateFinalConfigurationIncrementally(Map<String, AggregateConfiguration> configs) + throws Exception { + boolean isDbAccessible = false; + if (configs.get( + Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE) + != null) { + ConfigurationRepository.lookup().populateConfigurtaion( + Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE, + configs.remove( + Constants.DEFAULT_TENANT + Constants.KEY_ELEMENTS_DELEMETER + Constants.DB_NAMESPACE) + .getFinalConfiguration()); + isDbAccessible = ConfigurationUtils.executeDdlSql(ConfigurationRepository.lookup() + .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE) + .getString("createtablecql")); + if (isDbAccessible) { + ConfigurationUtils.executeDdlSql(ConfigurationRepository.lookup() + .getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE) + .getString("createmonitoringtablecql")); + } + } + + Set<String> modules = configs.keySet(); + for (String module : modules) { + if (isDbAccessible) { + DatabaseConfiguration config = + ConfigurationUtils.getDbConfigurationBuilder(module).getConfiguration(); + Configuration currentConfig = configs.get(module).getFinalConfiguration(); + Iterator<String> keys = currentConfig.getKeys(); + while (keys.hasNext()) { + String currentKey = keys.next(); + if (!(Constants.MODE_KEY.equals(currentKey) + || Constants.NAMESPACE_KEY.equals(currentKey) + || Constants.LOAD_ORDER_KEY.equals(currentKey))) { + if (!config.containsKey(currentKey)) { + Object propValue = currentConfig.getProperty(currentKey); + if (propValue instanceof Collection) { + config.addProperty(currentKey, propValue.toString()); + } else { + config.addProperty(currentKey, propValue); + } + } + } + } + } else { + ConfigurationRepository.lookup() + .populateConfigurtaion(module, configs.get(module).getFinalConfiguration()); + } + } + } + + @Override + public <T> T get(String tenant, String namespace, String key, Class<T> clazz, Hint... hints) { + + String[] tenantNamespaceArrayy = null; + if (tenant == null && namespace != null + && (tenantNamespaceArrayy = namespace.split(Constants.TENANT_NAMESPACE_SAPERATOR)).length + > 1) { + tenant = tenantNamespaceArrayy[0]; + namespace = tenantNamespaceArrayy[1]; + } + + tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase() + : Constants.DEFAULT_TENANT; + namespace = + ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase() + : Constants.DEFAULT_NAMESPACE; + T returnValue = null; + returnValue = (T) getInternal(tenant, namespace, key, + clazz.isPrimitive() ? getWrapperClass(clazz) : clazz, + hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC} + : hints); + if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue)) + && !Constants.DEFAULT_TENANT.equals(tenant)) { + returnValue = (T) getInternal(Constants.DEFAULT_TENANT, namespace, key, + clazz.isPrimitive() ? getWrapperClass(clazz) : clazz, + hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC} + : hints); + } + if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue)) + && !Constants.DEFAULT_NAMESPACE.equals(namespace)) { + returnValue = (T) getInternal(tenant, Constants.DEFAULT_NAMESPACE, key, + clazz.isPrimitive() ? getWrapperClass(clazz) : clazz, + hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC} + : hints); + } + if ((returnValue == null || ConfigurationUtils.isZeroLengthArray(clazz, returnValue)) + && !Constants.DEFAULT_NAMESPACE.equals(namespace) + && !Constants.DEFAULT_TENANT.equals(tenant)) { + returnValue = (T) getInternal(Constants.DEFAULT_TENANT, Constants.DEFAULT_NAMESPACE, key, + clazz.isPrimitive() ? getWrapperClass(clazz) : clazz, + hints == null || hints.length == 0 ? new Hint[]{Hint.EXTERNAL_LOOKUP, Hint.NODE_SPECIFIC} + : hints); + } + if (returnValue == null && clazz.isPrimitive()) { + return (T) ConfigurationUtils.getDefaultFor(clazz); + } else { + return returnValue; + } + } + + + /** + * Gets internal. + * + * @param <T> the type parameter + * @param tenant the tenant + * @param namespace the namespace + * @param key the key + * @param clazz the clazz + * @param hints the hints + * @return the internal + */ + protected <T> T getInternal(String tenant, String namespace, String key, Class<T> clazz, + Hint... hints) { + int processingHints = Hint.DEFAULT.value(); + if (hints != null) { + for (Hint hint : hints) { + processingHints = processingHints | hint.value(); + } + } + + if (tenant == null || tenant.trim().length() == 0) { + tenant = this.tenant.get(); + } else { + tenant = tenant.toUpperCase(); + } + if (namespace == null || namespace.trim().length() == 0) { + namespace = Constants.DEFAULT_NAMESPACE; + } else { + namespace = namespace.toUpperCase(); + } + if (key == null || key.trim().length() == 0) { + if (!clazz.isAnnotationPresent(Config.class)) { + throw new IllegalArgumentException("Key can't be null."); + } + } + if (clazz == null) { + throw new IllegalArgumentException("clazz is null."); + } + if (clazz.isPrimitive()) { + clazz = getWrapperClass(clazz); + } + try { + if (ConfigurationUtils.isWrapperClass(clazz) || clazz.isPrimitive()) { + Object obj = + ConfigurationUtils + .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace), + key, processingHints); + if (obj != null) { + if (ConfigurationUtils.isCollection(obj.toString())) { + obj = ConfigurationUtils.getCollectionString(obj.toString()); + } + String value = obj.toString().split(",")[0]; + value = ConfigurationUtils.processVariablesIfPresent(tenant, namespace, value); + return (T) getValue(value, clazz.isPrimitive() ? getWrapperClass(clazz) : clazz, + processingHints); + } else { + return null; + } + } else if (clazz.isArray() + && (clazz.getComponentType().isPrimitive() || ConfigurationUtils.isWrapperClass(clazz.getComponentType()))) { + Object obj = + ConfigurationUtils + .getProperty(ConfigurationRepository.lookup().getConfigurationFor(tenant, namespace), + key, processingHints); + if (obj != null) { + Class componentClass = clazz.getComponentType(); + if (clazz.getComponentType().isPrimitive()) { + componentClass = getWrapperClass(clazz.getComponentType()); + } + String collString = ConfigurationUtils.getCollectionString(obj.toString()); + ArrayList<String> tempCollection = new ArrayList<>(); + for (String itemValue : collString.split(",")) { + tempCollection + .add(ConfigurationUtils.processVariablesIfPresent(tenant, namespace, itemValue)); + } + Collection<T> collection = convert( + ConfigurationUtils.getCollectionString(Arrays.toString(tempCollection.toArray())), + componentClass, processingHints); + if (clazz.getComponentType().isPrimitive()) { + return (T) ConfigurationUtils.getPrimitiveArray(collection, clazz.getComponentType()); + } else { + return (T) collection + .toArray(getZeroLengthArrayFor(getWrapperClass(clazz.getComponentType()))); + } + } else { + return null; + } + } else if (clazz.isAnnotationPresent(Config.class)) { + return read(tenant, namespace, clazz, + (key == null || key.trim().length() == 0) ? "" : (key + "."), hints); + } else { + throw new IllegalArgumentException( + "Only pimitive classes, wrapper classes, corresponding array classes and any " + + "class decorated with @org.openecomp.config.api.Config are allowed as argument."); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + return null; + } + + + private <T> T read(String tenant, String namespace, Class<T> clazz, String keyPrefix, + Hint... hints) throws Exception { + Config confAnnot = + clazz.getAnnotation(Config.class); + if (confAnnot != null && confAnnot.key().length()>0 && !keyPrefix.endsWith(".")) { + keyPrefix += (confAnnot.key() + "."); + } + Constructor<T> constructor = clazz.getDeclaredConstructor(); + constructor.setAccessible(true); + T objToReturn = constructor.newInstance(); + for (Field field : clazz.getDeclaredFields()) { + field.setAccessible(true); + Config fieldConfAnnot = + field.getAnnotation(Config.class); + if (fieldConfAnnot != null) { + if (field.getType().isPrimitive() || ConfigurationUtils.isWrapperClass(field.getType()) + || (field.getType().isArray() && (field.getType().getComponentType().isPrimitive() + || ConfigurationUtils.isWrapperClass(field.getType().getComponentType()))) + || field.getType().getAnnotation(Config.class) != null) { + field.set(objToReturn, + get(tenant, namespace, keyPrefix + fieldConfAnnot.key(), field.getType(), hints)); + } else if (Collection.class.isAssignableFrom(field.getType())) { + Object obj = get(tenant, namespace, keyPrefix + fieldConfAnnot.key(), + ConfigurationUtils.getArrayClass(ConfigurationUtils.getCollectionGenericType(field)), + hints); + if (obj != null) { + List list = Arrays.asList((Object[]) obj); + Class clazzToInstantiate = null; + if (field.getType().isInterface()) { + clazzToInstantiate = + ConfigurationUtils.getConcreteCollection(field.getType()).getClass(); + } else if (Modifier.isAbstract(field.getType().getModifiers())) { + clazzToInstantiate = + ConfigurationUtils.getCompatibleCollectionForAbstractDef(field.getType()) + .getClass(); + } else { + clazzToInstantiate = field.getType(); + } + Constructor construct = + getConstructorWithArguments(clazzToInstantiate, Collection.class); + if (construct != null) { + construct.setAccessible(true); + field.set(objToReturn, construct.newInstance(list)); + } else if ((construct = + getConstructorWithArguments(clazzToInstantiate, Integer.class, Boolean.class, + Collection.class)) != null) { + construct.setAccessible(true); + field.set(objToReturn, construct.newInstance(list.size(), true, list)); + } + } + }else if (Map.class.isAssignableFrom(field.getType())){ + field.set(objToReturn, generateMap(tenant, namespace, keyPrefix+fieldConfAnnot.key())); + } + } + } + return objToReturn; + } + + private Constructor getConstructorWithArguments(Class clazz, Class... classes) { + try { + return clazz.getDeclaredConstructor(classes); + } catch (Exception exception) { + return null; + } + } + + private Class getWrapperClass(Class clazz) { + if (byte.class == clazz) { + return Byte.class; + } else if (short.class == clazz) { + return Short.class; + } else if (int.class == clazz) { + return Integer.class; + } else if (long.class == clazz) { + return Long.class; + } else if (float.class == clazz) { + return Float.class; + } else if (double.class == clazz) { + return Double.class; + } else if (char.class == clazz) { + return Character.class; + } else if (boolean.class == clazz) { + return Boolean.class; + } + return clazz; + } + + private <T> T getValue(Object obj, Class<T> clazz, int processingHint) { + if (obj == null || obj.toString().trim().length() == 0) { + return null; + } else { + obj = obj.toString().trim(); + } + if (String.class.equals(clazz)) { + if (obj.toString().startsWith("@") && ConfigurationUtils.isExternalLookup(processingHint)) { + String contents = ConfigurationUtils + .getFileContents(NonConfigResource.locate(obj.toString().substring(1).trim())); + if (contents == null) { + contents = ConfigurationUtils.getFileContents(obj.toString().substring(1).trim()); + } + if (contents != null) { + obj = contents; + } + } + return (T) obj.toString(); + } else if (Number.class.isAssignableFrom(clazz)) { + Double doubleValue = Double.valueOf(obj.toString()); + switch (clazz.getName()) { + case "java.lang.Byte": + Byte byteVal = doubleValue.byteValue(); + return (T) byteVal; + case "java.lang.Short": + Short shortVal = doubleValue.shortValue(); + return (T) shortVal; + case "java.lang.Integer": + Integer intVal = doubleValue.intValue(); + return (T) intVal; + case "java.lang.Long": + Long longVal = doubleValue.longValue(); + return (T) longVal; + case "java.lang.Float": + Float floatVal = doubleValue.floatValue(); + return (T) floatVal; + case "java.lang.Double": + Double doubleVal = doubleValue.doubleValue(); + return (T) doubleVal; + default: + } + } else if (Boolean.class.equals(clazz)) { + return (T) Boolean.valueOf(obj.toString()); + } else if (Character.class.equals(clazz)) { + return (T) Character.valueOf(obj.toString().charAt(0)); + } + return null; + } + + private <T> T[] getZeroLengthArrayFor(Class<T> clazz) { + Object obj = null; + if (clazz == int.class) { + obj = new int[]{}; + } else if (clazz == byte.class) { + obj = new byte[]{}; + } else if (clazz == short.class) { + obj = new short[]{}; + } else if (clazz == long.class) { + obj = new long[]{}; + } else if (clazz == float.class) { + obj = new float[]{}; + } else if (clazz == double.class) { + obj = new double[]{}; + } else if (clazz == boolean.class) { + obj = new boolean[]{}; + } else if (clazz == char.class) { + obj = new char[]{}; + } else if (clazz == Byte.class) { + obj = new Byte[]{}; + } else if (clazz == Short.class) { + obj = new Short[]{}; + } else if (clazz == Integer.class) { + obj = new Integer[]{}; + } else if (clazz == Long.class) { + obj = new Long[]{}; + } else if (clazz == Float.class) { + obj = new Float[]{}; + } else if (clazz == Double.class) { + obj = new Double[]{}; + } else if (clazz == Boolean.class) { + obj = new Boolean[]{}; + } else if (clazz == Character.class) { + obj = new Character[]{}; + } else if (clazz == String.class) { + obj = new String[]{}; + } + return (T[]) obj; + } + + private <T> Collection<T> convert(String commaSaperatedValues, Class<T> clazz, + int processingHints) { + ArrayList<T> collection = new ArrayList<>(); + for (String value : commaSaperatedValues.split(",")) { + try { + T type1 = getValue(value, clazz, processingHints); + if (type1 != null) { + collection.add(type1); + } + } catch (RuntimeException re) { + // do nothing + } + } + return collection; + } + + /** + * Shutdown. + */ + public void shutdown() { + if (changeNotifier != null) { + try { + changeNotifier.shutdown(); + ConfigurationDataSource.lookup().close(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + } + + @Override + public void removeConfigurationChangeListener(String tenant, String namespace, String key, + ConfigurationChangeListener myself) { + tenant = ConfigurationRepository.lookup().isValidTenant(tenant) ? tenant.toUpperCase() + : Constants.DEFAULT_TENANT; + namespace = + ConfigurationRepository.lookup().isValidNamespace(namespace) ? namespace.toUpperCase() + : Constants.DEFAULT_NAMESPACE; + if (key == null || key.trim().length() == 0) { + throw new IllegalArgumentException("Key can't be null."); + } + try { + changeNotifier.stopNotificationTowards(tenant, namespace, key, myself); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + @Override + public <T> Map<String, T> populateMap(String tenantId, String namespace, String key, Class<T> clazz){ + if (tenantId==null || tenantId.trim().length()==0){ + tenantId = this.tenant.get(); + }else{ + tenantId = tenantId.toUpperCase(); + } + if (namespace==null || namespace.trim().length()==0){ + namespace = Constants.DEFAULT_NAMESPACE; + }else{ + namespace = namespace.toUpperCase(); + } + Map<String, T> map = new HashMap<>(); + Iterator<String> keys ; + try { + if (ConfigurationRepository.lookup().isDBAccessible()){ + keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor( + Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+ Constants.KEY_ELEMENTS_DELEMETER+namespace}).iterator(); + }else{ + keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key); + } + while(keys.hasNext()){ + String k = keys.next(); + if (k.startsWith(key+".")){ + k = k.substring(key.length()+1); + String subkey = k.substring(0, k.indexOf(".")); + if (!map.containsKey(subkey)){ + map.put(subkey, get(tenantId, namespace, key+"."+subkey, clazz)); + } + } + } + }catch (Exception e){ + e.printStackTrace(); + } + return map; + } + + @Override + public Map generateMap(String tenantId, String namespace, String key){ + if (tenantId==null || tenantId.trim().length()==0){ + tenantId = this.tenant.get(); + }else{ + tenantId = tenantId.toUpperCase(); + } + if (namespace==null || namespace.trim().length()==0){ + namespace = Constants.DEFAULT_NAMESPACE; + }else{ + namespace = namespace.toUpperCase(); + } + Map map, parentMap = new HashMap<>(); + Iterator<String> keys ; + try { + if (ConfigurationRepository.lookup().isDBAccessible()){ + keys = ConfigurationUtils.executeSelectSql(ConfigurationRepository.lookup().getConfigurationFor( + Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE).getString("fetchkeysql"), new String[]{tenantId+ Constants.KEY_ELEMENTS_DELEMETER+namespace}).iterator(); + }else{ + if (key==null || key.trim().length()==0){ + keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(); + }else{ + keys = ConfigurationRepository.lookup().getConfigurationFor(tenantId, namespace).getKeys(key); + } + } + while(keys.hasNext()){ + map = parentMap; + String k = keys.next(); + + if (key!=null && key.trim().length()!=0 && !k.startsWith(key+".")){ + continue; + } + String value = getAsString(tenantId, namespace, k); + if (key!=null && key.trim().length()!=0 && k.startsWith(key+".")){ + k = k.substring(key.trim().length()+1); + } + + while(k.contains(".")){ + if (k.contains(".")){ + String subkey = k.substring(0, k.indexOf(".")); + k = k.substring(k.indexOf(".")+1); + if (!map.containsKey(subkey)){ + map.put(subkey, map=new HashMap<>()); + }else{ + map = (Map)map.get(subkey); + } + } + } + map.put(k, value); + } + }catch (Exception e){ + e.printStackTrace(); + } + return parentMap; + } + + + + +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationRepository.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationRepository.java new file mode 100644 index 0000000000..1c3bc1313f --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ConfigurationRepository.java @@ -0,0 +1,415 @@ +package org.onap.config.impl; + +import org.apache.commons.configuration2.CombinedConfiguration; +import org.apache.commons.configuration2.CompositeConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.FileBasedConfiguration; +import org.apache.commons.configuration2.builder.BasicConfigurationBuilder; +import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.onap.config.ConfigurationUtils; +import org.onap.config.Constants; + +import java.io.File; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +/** + * The type Configuration repository. + */ +public final class ConfigurationRepository { + + /** + * The Repo. + */ + static ConfigurationRepository repo; + private static Set<String> validCallers = Collections.unmodifiableSet(new HashSet<>(Arrays + .asList(ConfigurationChangeNotifier.NotificationData.class.getName(), + ConfigurationUtils.class.getName(), CliConfigurationImpl.class.getName(), + ConfigurationChangeNotifier.class.getName(), ConfigurationDataSource.class.getName(), + ConfigurationImpl.class.getName()))); + + static { + repo = new ConfigurationRepository(); + } + + private boolean dbAccessible = true; + private Set<String> tenants = new HashSet<>(); + private Set<String> namespaces = new HashSet<>(); + private LinkedHashMap<String, ConfigurationHolder> store = + new LinkedHashMap<String, ConfigurationHolder>(16, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + try { + return size() > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE) + .getInt("config.size.max"); + } catch (Exception exception) { + return false; + } + } + }; + + private ConfigurationRepository() { + if (repo != null) { + throw new RuntimeException("Illegal access to configuration."); + } + tenants.add(Constants.DEFAULT_TENANT); + namespaces.add(Constants.DEFAULT_NAMESPACE); + } + + /** + * Lookup configuration repository. + * + * @return the configuration repository + */ + public static ConfigurationRepository lookup() { + if (validCallers.contains(Thread.currentThread().getStackTrace()[2].getClassName())) { + return repo; + } + return null; + } + + /** + * Gets tenants. + * + * @return the tenants + */ + public Set<String> getTenants() { + return tenants; + } + + /** + * Gets namespaces. + * + * @return the namespaces + */ + public Set<String> getNamespaces() { + return namespaces; + } + + private void populateTenantsNamespace(String key, boolean sourcedFromDb) { + String[] array = key.split(Constants.KEY_ELEMENTS_DELEMETER); + if (!array[1].equalsIgnoreCase(Constants.DB_NAMESPACE)) { + if (!sourcedFromDb) { + dbAccessible = false; + } + tenants.add(array[0]); + namespaces.add(array[1]); + } + } + + /** + * Init tenants and namespaces. + */ + public void initTenantsAndNamespaces() { + try { + Collection<String> collection = ConfigurationUtils.executeSelectSql( + getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE) + .getString("fetchnamescql"), new String[]{}); + Iterator<String> iterator = collection.iterator(); + while (iterator.hasNext()) { + populateTenantsNamespace(iterator.next(), true); + } + } catch (Exception exception) { + //Log this later + } + } + + /** + * Is valid tenant boolean. + * + * @param tenant the tenant + * @return the boolean + */ + public boolean isValidTenant(String tenant) { + return tenant == null ? false : tenants.contains(tenant.toUpperCase()); + } + + /** + * Is valid namespace boolean. + * + * @param namespace the namespace + * @return the boolean + */ + public boolean isValidNamespace(String namespace) { + return namespace == null ? false : namespaces.contains(namespace.toUpperCase()); + } + + /** + * Gets configuration for. + * + * @param tenant the tenant + * @param namespace the namespace + * @return the configuration for + * @throws Exception the exception + */ + public Configuration getConfigurationFor(String tenant, String namespace) throws Exception { + ConfigurationHolder config; + String module = tenant + Constants.KEY_ELEMENTS_DELEMETER + namespace; + config = store.get(module); + if (config == null) { + config = new ConfigurationHolder(ConfigurationUtils + .getDbConfigurationBuilder(tenant + Constants.KEY_ELEMENTS_DELEMETER + namespace)); + store.put(module, config); + } + return config.getConfiguration(tenant + Constants.KEY_ELEMENTS_DELEMETER + namespace); + } + + /** + * Populate configurtaion. + * + * @param key the key + * @param builder the builder + */ + public void populateConfigurtaion(String key, Configuration builder) { + store.put(key, new ConfigurationHolder(builder)); + populateTenantsNamespace(key, false); + } + + /** + * Populate configurtaion. + * + * @param key the key + * @param builder the builder + * @throws Exception the exception + */ + public void populateConfigurtaion(String key, BasicConfigurationBuilder builder) + throws Exception { + store.put(key, new ConfigurationHolder(builder)); + } + + /** + * Populate override configurtaion. + * + * @param key the key + * @param file the file + * @throws Exception the exception + */ + public void populateOverrideConfigurtaion(String key, File file) throws Exception { + ConfigurationHolder holder = store.get(key); + if (holder == null) { + if (dbAccessible) { + holder = new ConfigurationHolder(ConfigurationUtils.getDbConfigurationBuilder(key)); + } else { + holder = new ConfigurationHolder(new CombinedConfiguration()); + } + store.put(key, holder); + } + holder.addOverrideConfiguration(file.getAbsolutePath(), + ConfigurationUtils.getConfigurationBuilder(file, true)); + populateTenantsNamespace(key, true); + } + + /** + * Refresh override configurtaion for. + * + * @param key the key + * @param index the index + * @throws Exception the exception + */ + public void refreshOverrideConfigurtaionFor(String key, int index) throws Exception { + ConfigurationHolder holder = store.get(key); + if (holder != null) { + holder.refreshOverrideConfiguration(index); + } + } + + /** + * Remove override configurtaion. + * + * @param file the file + * @throws Exception the exception + */ + public void removeOverrideConfigurtaion(File file) throws Exception { + Iterator<String> iterator = new ArrayList(store.keySet()).iterator(); + while (iterator.hasNext()) { + ConfigurationHolder holder = store.get(iterator.next()); + if (holder.containsOverrideConfiguration(file.getAbsolutePath())) { + holder.removeOverrideConfiguration(file.getAbsolutePath()); + } + } + + } + + private class ConfigurationHolder { + + /** + * The Builder. + */ + BasicConfigurationBuilder<Configuration> builder; + /** + * The Last configuration build time. + */ + Timestamp lastConfigurationBuildTime; + /** + * The Config. + */ + Configuration config; + /** + * The Composite. + */ + Configuration composite; + /** + * The Last config change timestamp. + */ + Timestamp lastConfigChangeTimestamp; + private Map<String, FileBasedConfigurationBuilder<FileBasedConfiguration>> + overrideConfiguration = new LinkedHashMap<>(); + + + /** + * Instantiates a new Configuration holder. + * + * @param builder the builder + */ + public ConfigurationHolder(BasicConfigurationBuilder builder) { + this.builder = builder; + } + + /** + * Instantiates a new Configuration holder. + * + * @param builder the builder + */ + public ConfigurationHolder(Configuration builder) { + this.config = builder; + } + + /** + * Refresh override configuration. + * + * @param index the index + */ + public void refreshOverrideConfiguration(int index) { + int count = -1; + for (FileBasedConfigurationBuilder overrides : overrideConfiguration.values()) { + try { + if (++count == index) { + overrides.save(); + overrides.resetResult(); + } + } catch (ConfigurationException exception) { + //do nothing + } + } + } + + /** + * Add override configuration. + * + * @param path the path + * @param builder the builder + */ + public void addOverrideConfiguration(String path, + BasicConfigurationBuilder<FileBasedConfiguration> builder) { + overrideConfiguration.put(path.toUpperCase(), (FileBasedConfigurationBuilder) builder); + getEffectiveConfiguration(config, overrideConfiguration.values()); + } + + /** + * Remove override configuration. + * + * @param path the path + */ + public void removeOverrideConfiguration(String path) { + overrideConfiguration.remove(path.toUpperCase()); + getEffectiveConfiguration(config, overrideConfiguration.values()); + } + + /** + * Contains override configuration boolean. + * + * @param path the path + * @return the boolean + */ + public boolean containsOverrideConfiguration(String path) { + return overrideConfiguration.containsKey(path.toUpperCase()); + } + + /** + * Gets configuration. + * + * @param namespace the namespace + * @return the configuration + * @throws Exception the exception + */ + public Configuration getConfiguration(String namespace) throws Exception { + if (config == null) { + config = builder.getConfiguration(); + lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis()); + } else if (lastConfigurationBuildTime != null + && System.currentTimeMillis() - lastConfigurationBuildTime.getTime() + > getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE) + .getInt("config.refresh.interval")) { + Timestamp temp = getLastUpdateTimestampFor(namespace); + if ((temp != null) + && (lastConfigChangeTimestamp == null + || temp.getTime() > lastConfigChangeTimestamp.getTime())) { + builder.resetResult(); + config = builder.getConfiguration(); + lastConfigChangeTimestamp = temp; + getEffectiveConfiguration(config, overrideConfiguration.values()); + } + lastConfigurationBuildTime = new Timestamp(System.currentTimeMillis()); + } + if (composite == null && overrideConfiguration.size() != 0) { + composite = getEffectiveConfiguration(config, overrideConfiguration.values()); + } + return overrideConfiguration.size() == 0 ? config : composite; + } + + private Configuration getEffectiveConfiguration(Configuration configuration, + Collection<FileBasedConfigurationBuilder<FileBasedConfiguration>> list) { + try { + CompositeConfiguration cc = new CompositeConfiguration(); + for (FileBasedConfigurationBuilder<FileBasedConfiguration> b : list) { + cc.addConfiguration(b.getConfiguration()); + } + cc.addConfiguration(configuration); + composite = cc; + return composite; + } catch (Exception exception) { + return null; + } + } + + /** + * Gets last update timestamp for. + * + * @param namespace the namespace + * @return the last update timestamp for + */ + public Timestamp getLastUpdateTimestampFor(String namespace) { + Timestamp timestamp = null; + + try { + Collection<String> collection = ConfigurationUtils.executeSelectSql( + getConfigurationFor(Constants.DEFAULT_TENANT, Constants.DB_NAMESPACE) + .getString("fetchlastchangecql"), new String[]{namespace}); + if (!collection.isEmpty()) { + timestamp = new Timestamp(Long.valueOf(((ArrayList) collection).get(0).toString())); + } + } catch (Exception exception) { + //Log this later + } + + return timestamp; + } + + + } + + public boolean isDBAccessible(){ + return dbAccessible; + } + + +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ContextListener.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ContextListener.java new file mode 100644 index 0000000000..cf87db936d --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/ContextListener.java @@ -0,0 +1,28 @@ +package org.onap.config.impl; + +import static org.onap.config.Constants.MBEAN_NAME; + +import java.lang.management.ManagementFactory; +import javax.management.ObjectName; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; +import org.onap.config.api.ConfigurationManager; + +@WebListener +public class ContextListener implements ServletContextListener { + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + try { + ManagementFactory.getPlatformMBeanServer().unregisterMBean(new ObjectName(MBEAN_NAME)); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + @Override + public void contextInitialized(ServletContextEvent arg0) { + ConfigurationManager.lookup(); + } +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/YamlConfiguration.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/YamlConfiguration.java new file mode 100644 index 0000000000..dc6785fd73 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/impl/YamlConfiguration.java @@ -0,0 +1,18 @@ +package org.onap.config.impl; + +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.virtlink.commons.configuration2.jackson.JacksonConfiguration; +import org.apache.commons.configuration2.HierarchicalConfiguration; +import org.apache.commons.configuration2.tree.ImmutableNode; + +public class YamlConfiguration extends JacksonConfiguration { + + protected YamlConfiguration(HierarchicalConfiguration<ImmutableNode> config) { + super(new YAMLFactory(), config); + } + + public YamlConfiguration() { + super(new YAMLFactory()); + } + +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationMode.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationMode.java new file mode 100644 index 0000000000..826d53e6bc --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationMode.java @@ -0,0 +1,5 @@ +package org.onap.config.type; + +public enum ConfigurationMode { + OVERRIDE, UNION, MERGE +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationQuery.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationQuery.java new file mode 100644 index 0000000000..6aec7c27da --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationQuery.java @@ -0,0 +1,94 @@ +package org.onap.config.type; + +import org.onap.config.Constants; + +public class ConfigurationQuery { + + String tenant = Constants.DEFAULT_TENANT; + String namespace = Constants.DEFAULT_NAMESPACE; + String key; + boolean fallback; + boolean externalLookup; + boolean latest; + private boolean nodeSpecific; + + public ConfigurationQuery fallback(boolean fallback) { + this.fallback = fallback; + return this; + } + + public ConfigurationQuery latest(boolean val) { + this.latest = val; + return this; + } + + public ConfigurationQuery nodeSpecific(boolean val) { + this.nodeSpecific = val; + return this; + } + + public ConfigurationQuery externalLookup(boolean val) { + this.externalLookup = val; + return this; + } + + /** + * Tenant configuration query. + * + * @param id the id + * @return the configuration query + */ + public ConfigurationQuery tenant(String id) { + if (id != null) { + tenant = id; + } + return this; + } + + + /** + * Namespace configuration query. + * + * @param id the id + * @return the configuration query + */ + public ConfigurationQuery namespace(String id) { + if (id != null) { + namespace = id; + } + return this; + } + + public ConfigurationQuery key(String id) { + key = id; + return this; + } + + public String getTenant() { + return tenant.toUpperCase(); + } + + public String getNamespace() { + return namespace.toUpperCase(); + } + + public String getKey() { + return key; + } + + public boolean isFallback() { + return fallback; + } + + public boolean isNodeSpecific() { + return nodeSpecific; + } + + public boolean isExternalLookup() { + return externalLookup; + } + + public boolean isLatest() { + return latest; + } +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationType.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationType.java new file mode 100644 index 0000000000..54253fa754 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationType.java @@ -0,0 +1,5 @@ +package org.onap.config.type; + +public enum ConfigurationType { + PROPERTIES, XML, JSON, YAML +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationUpdate.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationUpdate.java new file mode 100644 index 0000000000..739dd776bf --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/java/org/onap/config/type/ConfigurationUpdate.java @@ -0,0 +1,33 @@ +package org.onap.config.type; + +public class ConfigurationUpdate extends ConfigurationQuery { + private String value; + private boolean nodeOverride; + + public ConfigurationUpdate value(String val) { + value = val; + return this; + } + + public ConfigurationUpdate nodeOverride(boolean val) { + nodeOverride = val; + return this; + } + + /** + * Gets value. + * + * @return the value + */ + public String getValue() { + if (value != null && value.split(",").length > 1 && !value.matches("^\\[.*\\]$")) { + return "[" + value + "]"; + } + return value; + } + + public boolean isNodeOverride() { + return nodeOverride; + } + +} diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/resources/META-INF/services/org.onap.config.api.ConfigurationManager b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/resources/META-INF/services/org.onap.config.api.ConfigurationManager new file mode 100644 index 0000000000..173484f1a7 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/resources/META-INF/services/org.onap.config.api.ConfigurationManager @@ -0,0 +1 @@ +org.onap.config.impl.CliConfigurationImpl
\ No newline at end of file diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/resources/config-system.properties b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/resources/config-system.properties new file mode 100644 index 0000000000..cfe91e6c7d --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/resources/config-system.properties @@ -0,0 +1,22 @@ +driverClassName=com.github.adejanovski.cassandra.jdbc.CassandraDriver +jdbcURL=jdbc:${dbname}://${dbhost}:${dbport}/${configdb} +dbuser= +dbpassword= +config.Table=configuration +config.monitor.Table=configuration_change +configKey=key +configValue=value +configNameColumn=name +configdb=dox +dbhost= +dbport=9042 +dbname=cassandra +createtablecql=create table if not exists ${configdb}.${config.Table} (name text\, key text\, value text\, PRIMARY KEY (name\, key)) with clustering order by (key asc) +createmonitoringtablecql=create table if not exists ${configdb}.${config.monitor.Table} (name text\, changed_when bigint\, key text\, old_value text\, new_value text\, PRIMARY KEY (name\, changed_when)) with clustering order by (changed_when desc) +insertconfigurationchangecql=insert into ${configdb}.${config.monitor.Table} (name\, changed_when\, key\, old_value\, new_value) values(?\, ?\, ?\, ?\, ?) +fetchkeysql=select ${configKey} from ${config.Table} where ${configNameColumn}=? +fetchlastchangecql=select changed_when from ${configdb}.${config.monitor.Table} where name=? limit 1 +fetchnamescql=select distinct name from ${configdb}.${config.Table} +config.size.max=100 +config.refresh.interval=30000 +event.fetch.delay=5000
\ No newline at end of file diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/main/resources/management.properties b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/resources/management.properties new file mode 100644 index 0000000000..9874394726 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/main/resources/management.properties @@ -0,0 +1,7 @@ +com.sun.management.jmxremote=true +#com.sun.management.jmxremote.port=9999 +#com.sun.management.jmxremote.local.only=false +#com.sun.management.jmxremote.authenticate=false +#com.sun.management.jmxremote.password.file=resources/jmxremote.password +#com.sun.management.jmxremote.access.file=resources/jmxremote.access +#com.sun.management.jmxremote.ssl=false
\ No newline at end of file diff --git a/common/onap-common-configuration-management/onap-configuration-management-core/src/test/java/org/onap/config/ConfigurationUtilsTest.java b/common/onap-common-configuration-management/onap-configuration-management-core/src/test/java/org/onap/config/ConfigurationUtilsTest.java new file mode 100644 index 0000000000..90966fccf6 --- /dev/null +++ b/common/onap-common-configuration-management/onap-configuration-management-core/src/test/java/org/onap/config/ConfigurationUtilsTest.java @@ -0,0 +1,32 @@ +package org.onap.config; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class ConfigurationUtilsTest { + @Test + public void testCommaList() { + List list = Arrays.asList("1", "2", 3); + String commaSeparatedList = ConfigurationUtils.getCommaSeparatedList(list); + list.forEach(o -> assertTrue(commaSeparatedList.contains(o.toString()))); + } + + @Test + public void testCommaListWithNullAndEmptyStrings() { + List list = Arrays.asList(null, "", " "); + String commaSeparatedList = ConfigurationUtils.getCommaSeparatedList(list); + assertTrue(commaSeparatedList.isEmpty()); + } + + @Test + public void testGetArrayClassFunction() { + assertEquals(String[].class , ConfigurationUtils.getArrayClass(String.class)); + assertNull(ConfigurationUtils.getArrayClass(ConfigurationUtilsTest.class)); + } +}
\ No newline at end of file |