aboutsummaryrefslogtreecommitdiffstats
path: root/cdf/src/cdf-prop-value/cdf-util/src/main/java/org/onap/dcae/cdf/util/config/Configuration.java
diff options
context:
space:
mode:
Diffstat (limited to 'cdf/src/cdf-prop-value/cdf-util/src/main/java/org/onap/dcae/cdf/util/config/Configuration.java')
-rw-r--r--cdf/src/cdf-prop-value/cdf-util/src/main/java/org/onap/dcae/cdf/util/config/Configuration.java579
1 files changed, 579 insertions, 0 deletions
diff --git a/cdf/src/cdf-prop-value/cdf-util/src/main/java/org/onap/dcae/cdf/util/config/Configuration.java b/cdf/src/cdf-prop-value/cdf-util/src/main/java/org/onap/dcae/cdf/util/config/Configuration.java
new file mode 100644
index 0000000..db54276
--- /dev/null
+++ b/cdf/src/cdf-prop-value/cdf-util/src/main/java/org/onap/dcae/cdf/util/config/Configuration.java
@@ -0,0 +1,579 @@
+/*
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this code except in compliance
+ with the License. You may obtain a copy of the License
+ at http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+*/
+package org.onap.dcae.cdf.util.config;
+
+import java.io.*;
+import java.util.*;
+import java.net.*;
+import java.util.logging.*;
+import org.onap.dcae.cdf.util.common.*;
+import org.onap.dcae.cdf.util.threads.*;
+
+/**
+ * Class to monitor configuration parameters and notify
+ * other objects when they change
+ */
+
+public class Configuration extends Thread implements Configurable {
+ /**
+ * Time between checks of config file in milliseconds
+ */
+ private static int INTERVAL = 30000;
+ private int interval = INTERVAL;
+ /**
+ * Minimum age of config file before loading it in milliseconds
+ */
+ private static final int MINAGE = 30000;
+ private int minage = MINAGE;
+ /**
+ * Value returned by getInstance() method
+ */
+ private static Configuration defaultInstance = new Configuration();
+ /**
+ * Value returned by getLocalIP() method
+ */
+ private static String defaultLocalIP;
+ private static String defaultLocalIPinHex;
+ private static String defaultCanonicalHostName;
+ static {
+ try {
+ InetAddress ia = InetAddress.getLocalHost();
+ defaultLocalIP = ia.getHostAddress();
+ byte b[] = ia.getAddress();
+ defaultLocalIPinHex = Convert.toHexString(b);
+ defaultCanonicalHostName = ia.getCanonicalHostName();
+ } catch (Exception e) {
+ defaultLocalIP = "127.0.0.1";
+ defaultLocalIPinHex = "7F000001";
+ defaultCanonicalHostName = "localhost";
+ }
+ }
+ /**
+ * Get an IP address for this machine
+ */
+ public static String getLocalIP() {
+ return defaultLocalIP;
+ }
+ /**
+ * Get an IP address for this machine
+ */
+ public static String getLocalIPinHex() {
+ return defaultLocalIPinHex;
+ }
+ /**
+ * Get a host name for this machine
+ */
+ public static String getCanonicalHostName() {
+ return defaultCanonicalHostName;
+ }
+ /**
+ * Get a default global instance
+ */
+ public static Configuration getInstance() {
+ return defaultInstance;
+ }
+ /**
+ * The current configuration
+ */
+ private ResourceBundle config;
+ /**
+ * Where to log when things go wrong
+ */
+ private static Logger logger = Logger.getLogger(Configuration.class.getName());
+ /**
+ * The config file to read
+ */
+ private File file;
+ /**
+ * The name of the config to read, when overriding the file.
+ */
+ private String filename;
+ /**
+ * The last modified date of the config file
+ */
+ private long curdate;
+ /**
+ * Should we stop scanning for config file updates?
+ */
+ private boolean closed;
+ static boolean closeAll = false;
+ /**
+ * Have we started scanning for config file updates?
+ */
+ private boolean initialized;
+ /**
+ * The name of the background thread monitoring the file.
+ */
+ private static String monitorThreadName = "Configuration Monitor";
+ /**
+ * How we keep track of registered Configurables.
+ */
+ private ConfigurationRegistry configurationRegistry = new ConfigurationRegistry();
+ /**
+ * included file.
+ */
+ private Configuration subConfig = null;
+ private String subFile = null;
+
+ public void reConfigure() {
+ configurationRegistry.reConfigureAll(logger);
+ }
+
+ /**
+ * Create an instance using the default configuration file
+ * "configfile.properties" from the class path
+ */
+ public Configuration() {
+ // logger.fine("Configuration()");
+ }
+ /**
+ * Create an instance using a configuration file
+ * "FILENAME.properties" from the class path
+ */
+ public Configuration(String filename) {
+ // logger.fine("Configuration(" + filename + ")");
+ this.filename = filename;
+ }
+ /**
+ * Create an instance using a specific configuration file
+ */
+ public Configuration(File file) {
+ this.file = file;
+ // logger.fine("Configuration(File)");
+ }
+
+ /**
+ * Change the configuration file to use
+ */
+ public void setConfig(File file) {
+ this.file = file;
+ curdate = 0;
+ interrupt();
+ }
+ /**
+ * Reset the interval used for rechecking the file.
+ * @param interval
+ */
+ public synchronized void setInterval(int interval) {
+ this.interval = interval;
+ }
+ /**
+ * Reset the default interval used for rechecking the file.
+ * @param interval
+ */
+ public synchronized void setDefaultInterval(int interval) {
+ this.INTERVAL = interval;
+ }
+ /**
+ * Reset the minimum age the file must be before being reread.
+ * This is used to prevent reading the file while it is being written, say by vi.
+ * @param minage
+ */
+ public synchronized void setMinage(int minage) {
+ this.minage = minage;
+ }
+ /**
+ * Stop checking for config changes
+ */
+ public void close() {
+ checkinit();
+ closed = true;
+ if (Thread.currentThread() == this) {
+ return;
+ }
+ interrupt();
+ try {
+ join();
+ } catch (Exception e) {
+ }
+ }
+ /**
+ * Check the config file to see if it has changed
+ */
+ private synchronized void check() {
+ long now = System.currentTimeMillis();
+ if (logger.isLoggable(Level.FINE)) logger.fine("check(): now=" + Long.toString(now));
+ try {
+ long ndate = file.lastModified();
+ if (logger.isLoggable(Level.FINE)) logger.fine("file=" + file + ", ndate=" + Long.toString(ndate) + ", curdate=" + Long.toString(curdate,10));
+ if (ndate == curdate || (now < ndate + minage && curdate != 0)) {
+ return;
+ }
+ if (logger.isLoggable(Level.FINE)) logger.fine("reloading file=" + file);
+ FileInputStream in = new FileInputStream(file);
+ config = new PropertyResourceBundle(in);
+ in.close();
+ try {
+ String inc = config.getString("include");
+ if ((inc != null) && !inc.equals("")) {
+ subFile = inc;
+ subConfig = new Configuration(subFile);
+ subConfig.registerConfigurable(this);
+ }
+ } catch (Exception e) {
+ }
+
+ curdate = ndate;
+ configurationRegistry.reConfigureAll(logger);
+ // logger.info("CNFG0006: Configuration '" + file + "' reloaded");
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "DAIS0048 Unrecoverable configuration error CNFG0004: Configuration file '" + file + "' inaccessible", e);
+ }
+ }
+ /**
+ * Make sure we're initialized and read the config file
+ * if necessary
+ */
+ public void checkinit() {
+ // System.out.println("checkinit()");
+ if (initialized) {
+ return;
+ }
+ initialized = true;
+ try {
+ if (file == null) {
+ if (filename == null)
+ filename = System.getProperty("configfile", "configfile");
+ // logger.info("DAIS0073 0.8.73 >>> filename=" + filename);
+ if (filename.charAt(0) == '/') {
+ // logger.info("DAIS0073 0.8.73 filename has leading slash: " + filename);
+ file = new File(filename);
+ } else {
+ URI uri = getClass().getClassLoader().getResource(filename + ".properties").toURI();
+ // logger.info("DAIS0073 0.8.73 uri=" + uri.toString());
+ file = new File(uri);
+ }
+ }
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "DAIS0048 Unrecoverable configuration error CNFG0003: Cannot find configuration file '" + filename + "'", e);
+ }
+ check();
+ setDaemon(true);
+ setName(monitorThreadName);
+ start();
+ }
+ /**
+ * Check the config file to see if it has changed
+ */
+ public void run() {
+ if (logger.isLoggable(Level.FINE)) logger.fine("Configuration::run()");
+ while (!closed && !closeAll) {
+ try {
+ if (logger.isLoggable(Level.FINE)) logger.fine("sleeping " + Integer.toString(interval) + ", id=" + Long.toString(Thread.currentThread().getId()) + ", file=" + filename);
+ Thread.sleep(interval);
+ } catch (Exception e) {
+ }
+ if (logger.isLoggable(Level.FINE)) {
+ Thread currentThread = Thread.currentThread();
+ logger.fine("checking id=" + Long.toString((currentThread != null) ? currentThread.getId() : -1) + ", file=" + filename);
+ }
+ check();
+ }
+ }
+
+ public static void wakeAllThreads() {
+ try {
+ Thread[] threads = ThreadUtils.getNamedThreads( monitorThreadName );
+ for ( Thread thread : threads )
+ thread.interrupt();
+ } catch (Exception e) {
+ }
+ }
+
+ public static void closeAllThreads() {
+ closeAll = true;
+ wakeAllThreads();
+ }
+
+ /**
+ * Forward this Configurable to the ConfigurationRegistry to be registered.
+ */
+ public void registerConfigurable(Configurable element) {
+ configurationRegistry.registerConfigurable(element);
+ }
+ /**
+ * Forward this Configurable to the ConfigurationRegistry to be deRegistered.
+ */
+ public void deRegisterConfigurable(Configurable element) {
+ configurationRegistry.deRegisterConfigurable(element);
+ }
+
+ /**
+ * Get a configuration parameter as a String.
+ * If undefined, return null and log an error.
+ * @return String
+ */
+ public String getString(String name) {
+ return getString(name, null, true);
+ }
+ /**
+ * Get a configuration parameter as a String.
+ * If undefined, return the specified default value.
+ * @return String
+ */
+ public String getString(String name, String deflt) {
+ return getString(name, deflt, false);
+ }
+
+ public static String trimQuotes(String str) {
+ if (str == null) return null;
+ str = str.trim();
+ int len = str.length();
+ if (len < 2) return str;
+ char startChar = str.charAt(0);
+ char endChar = str.charAt(len-1);
+ boolean startDoubleQuote = startChar == '"';
+ boolean startSingleQuote = startChar == '\'';
+ boolean endDoubleQuote = endChar == '"';
+ boolean endSingleQuote = endChar == '\'';
+ if ((startDoubleQuote && endDoubleQuote) ||
+ (startSingleQuote && endSingleQuote)) {
+ return str.substring(1, len-1);
+ } else {
+ return str;
+ }
+ }
+
+ /**
+ * Get a configuration parameter as a String.
+ * If undefined, return the specified default value.
+ * If complaining, log an error.
+ * @return String
+ */
+ public String getString(String name, String deflt, boolean complain) {
+ checkinit();
+ try {
+ return trimQuotes(config.getString(name));
+ } catch (Exception e) {
+ if (subConfig != null) {
+ try {
+ return subConfig.getString(name, deflt, complain);
+ } catch (Exception e2) {
+ }
+ }
+ if (complain)
+ logger.log(Level.SEVERE, "DAIS0048 Unrecoverable configuration error CNFG0001: '" + filename + "': Configuration property " + name + " must be defined", e);
+ return deflt;
+ }
+ }
+
+ /**
+ * Get a configuration parameter as a String encoded using URL % escapes.
+ * If undefined, return null and log an error.
+ * @return String
+ */
+ public String getDecodedString(String name) {
+ return getDecodedString(name, null, true);
+ }
+ /**
+ * Get a configuration parameter as a String encoded using URL % escapes.
+ * If undefined, return the specified default value.
+ * @return String
+ */
+ public String getDecodedString(String name, String deflt) {
+ return getDecodedString(name, deflt, false);
+ }
+ /**
+ * Get a configuration parameter as a String encoded using URL % escapes.
+ * If undefined, return the specified default value.
+ * If complaining, log an error.
+ * @return String
+ */
+ public String getDecodedString(String name, String deflt, boolean complain) {
+ checkinit();
+ try {
+ return URLDecoder.decode(config.getString(name), "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ logger.log(Level.SEVERE, "DAIS0048 Unrecoverable configuration error CNFG0007: UTF-8 is not recognized as a character set encoding", e);
+ return deflt;
+ } catch (Exception e) {
+ if (complain)
+ logger.log(Level.SEVERE, "DAIS0048 Unrecoverable configuration error CNFG0001: '" + filename + "': Configuration property " + name + " must be defined", e);
+ return deflt;
+ }
+ }
+
+ /**
+ * Get a configuration parameter as a String[].
+ * If undefined, return null and log an error.
+ * @return String[]
+ */
+ public String[] getStrings(String name) {
+ return getStrings(name, null, "[ \t,]+", true);
+ }
+ /**
+ * Get a configuration parameter as a String[].
+ * If undefined, return the specified default.
+ * @return String[]
+ */
+ public String[] getStrings(String name, String[] deflt) {
+ return getStrings(name, deflt, "[ \t,]+", false);
+ }
+ /**
+ * Get a configuration parameter as a String[].
+ * If undefined, return the specified default
+ * @return String[]
+ */
+ public String[] getStrings(String name, String[] deflt, String pattern, boolean complain) {
+ name = getString(name, null, complain);
+ if (name == null) {
+ return deflt;
+ }
+ return name.trim().split(pattern);
+ }
+
+ /**
+ * Get a configuration parameter as a String[], each String encoded using URL % escapes.
+ * If undefined, return null and log an error.
+ * @return String[]
+ */
+ public String[] getDecodedStrings(String name) {
+ return getDecodedStrings(name, null, "[ \t,]+", true);
+ }
+ /**
+ * Get a configuration parameter as a String[], each String encoded using URL % escapes.
+ * If undefined, return the specified default.
+ * @return String[]
+ */
+ public String[] getDecodedStrings(String name, String[] deflt) {
+ return getDecodedStrings(name, deflt, "[ \t,]+", false);
+ }
+ /**
+ * Get a configuration parameter as a String[], each String encoded using URL % escapes.
+ * If undefined, return the specified default.
+ * @return String[]
+ */
+ public String[] getDecodedStrings(String name, String[] deflt, String pattern) {
+ return getDecodedStrings(name, deflt, pattern, false);
+ }
+ /**
+ * Get a configuration parameter as a String[], each String encoded using URL % escapes.
+ * If undefined, return the specified default.
+ * @return String[]
+ */
+ public String[] getDecodedStrings(String name, String[] deflt, String pattern, boolean complain) {
+ name = getString(name, null, complain);
+ if (name == null) {
+ return deflt;
+ }
+ String[] strs = (name.trim().split(pattern));
+ try {
+ for (int i = 0; i < strs.length; i++) {
+ strs[i] = URLDecoder.decode(strs[i], "UTF-8");
+ }
+ } catch (UnsupportedEncodingException e) {
+ logger.log(Level.SEVERE, "DAIS0048 Unrecoverable configuration error CNFG0007: UTF-8 is not recognized as a character set encoding", e);
+ }
+ return strs;
+ }
+
+ /**
+ * Get a configuration parameter as a long. If undefined or non-numeric, return -1 and log an error.
+ */
+ public long getLong(String name) {
+ return getLong(name, -1L);
+ }
+ /**
+ * Get a configuration parameter as a long. If undefined, return the specified default
+ * If non-numeric, return the specified default and log an error.
+ */
+ public long getLong(String name, long deflt) {
+ String value = getString(name, null);
+ if (value == null) {
+ return deflt;
+ }
+ try {
+ return Long.parseLong(value.trim());
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "DAIS0048 Unrecoverable configuration error CNFG0002: '" + filename + "': Configuration property " + name + " must be numeric", e);
+ return deflt;
+ }
+ }
+
+ /**
+ * Get a configuration parameter as an int. If undefined or non-numeric, return -1 and log an error.
+ */
+ public int getInt(String name) {
+ return getInt(name, -1);
+ }
+ /**
+ * Get a configuration parameter as an int. If undefined, return the specified default
+ * If non-numeric, return the specified default and log an error.
+ */
+ public int getInt(String name, int deflt) {
+ String value = getString(name, null);
+ if (value == null) {
+ return deflt;
+ }
+ try {
+ return Integer.parseInt(value.trim());
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "DAIS0048 Unrecoverable configuration error CNFG0002: '" + filename + "': Configuration property " + name + " must be numeric", e);
+ return deflt;
+ }
+ }
+
+ /**
+ * Get a configuration parameter as an boolean. If undefined or non-numeric, return false and log an error.
+ */
+ public boolean getBoolean(String name) {
+ return getBoolean(name, false);
+ }
+ /**
+ * Get a configuration parameter as an boolean. If undefined, return the specified default
+ * If non-numeric, return the specified default and log an error.
+ */
+ public boolean getBoolean(String name, boolean deflt) {
+ String value = getString(name, null);
+ if (value == null) {
+ return deflt;
+ }
+ try {
+ return Boolean.parseBoolean(value.trim());
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "DAIS0048 Unrecoverable configuration error CNFG0002: '" + filename + "': Configuration property " + name + " must be true/false", e);
+ return deflt;
+ }
+ }
+
+ /**
+ * Get a configuration parameter as a double. If undefined or non-numeric, return -1 and log an error.
+ */
+ public double getDouble(String name) {
+ return getDouble(name, -1);
+ }
+ /**
+ * Get a configuration parameter as a double. If undefined, return the specified default
+ * If non-numeric, return the specified default and log an error.
+ */
+ public double getDouble(String name, double deflt) {
+ String value = getString(name, null);
+ if (value == null) {
+ return deflt;
+ }
+ try {
+ return Double.parseDouble(value);
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "DAIS0048 Unrecoverable configuration error CNFG0002: '" + filename + "': Configuration property " + name + " must be numeric", e);
+ return deflt;
+ }
+ }
+
+ public Enumeration getKeys() {
+ checkinit();
+ return (config != null) ? config.getKeys() : null;
+ }
+}