diff options
16 files changed, 908 insertions, 927 deletions
diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedService.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedService.java index 7a6ca0a0..45ad85a8 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedService.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedService.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-utils * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,17 +26,22 @@ package org.onap.policy.drools.utils; * 'OrderedServiceImpl' for more details. */ @FunctionalInterface -public interface OrderedService -{ - /** - * @return an integer sequence number, which determines the order of a list - * of objects implementing this interface - */ - public int getSequenceNumber(); - - - /** - * @return the name of the ordered service - */ - public default String getName() {return this.getClass().getName();} +public interface OrderedService { + /** + * Get sequence number. + * + * @return an integer sequence number, which determines the order of a list + * of objects implementing this interface + */ + public int getSequenceNumber(); + + + /** + * Get the name. + * + * @return the name of the ordered service + */ + public default String getName() { + return this.getClass().getName(); + } } diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedServiceImpl.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedServiceImpl.java index d0b451f1..fa0a045c 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedServiceImpl.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedServiceImpl.java @@ -33,111 +33,103 @@ import org.slf4j.LoggerFactory; * This class is a template for building a sorted list of service instances, * which are discovered and created using 'ServiceLoader'. */ -public class OrderedServiceImpl<T extends OrderedService> -{ - // logger - private static Logger logger = LoggerFactory.getLogger(OrderedServiceImpl.class); - - // sorted list of instances implementing the service - private List<T> implementers = null; +public class OrderedServiceImpl<T extends OrderedService> { + // logger + private static Logger logger = LoggerFactory.getLogger(OrderedServiceImpl.class); - // 'ServiceLoader' that is used to discover and create the services - private ServiceLoader<T> serviceLoader = null; + // sorted list of instances implementing the service + private List<T> implementers = null; - // use this to ensure that we only use one unique instance of each class - @SuppressWarnings("rawtypes") - private static HashMap<Class,OrderedService> classToSingleton = - new HashMap<>(); + // 'ServiceLoader' that is used to discover and create the services + private ServiceLoader<T> serviceLoader = null; - /** - * Constructor - create the 'ServiceLoader' instance - * - * @param clazz the class object associated with 'T' (I supposed it could - * be a subclass, but I'm not sure this is useful) - */ - public OrderedServiceImpl(Class<T> clazz) - { - // This constructor wouldn't be needed if 'T.class' was legal - serviceLoader = ServiceLoader.load(clazz); - } + // use this to ensure that we only use one unique instance of each class + @SuppressWarnings("rawtypes") + private static HashMap<Class,OrderedService> classToSingleton = new HashMap<>(); - /** - * @return the sorted list of services implementing interface 'T' discovered - * by 'ServiceLoader'. - */ - public synchronized List<T> getList() - { - if (implementers == null) - { - rebuildList(); - } - return implementers; - } + /** + * Constructor - create the 'ServiceLoader' instance. + * + * @param clazz the class object associated with 'T' (I supposed it could + * be a subclass, but I'm not sure this is useful) + */ + public OrderedServiceImpl(Class<T> clazz) { + // This constructor wouldn't be needed if 'T.class' was legal + serviceLoader = ServiceLoader.load(clazz); + } - /** - * This method is called by 'getList', but could also be called directly if - * we were running with a 'ClassLoader' that supported the dynamic addition - * of JAR files. In this case, it could be invoked in order to discover any - * new services implementing interface 'T'. This is probably a relatively - * expensive operation in terms of CPU and elapsed time, so it is best if it - * isn't invoked too frequently. - * - * @return the sorted list of services implementing interface 'T' discovered - * by 'ServiceLoader'. - */ - @SuppressWarnings("unchecked") - public synchronized List<T> rebuildList() - { - // build a list of all of the current implementors - List<T> tmp = new LinkedList<>(); - for (T service : serviceLoader) - { - tmp.add((T)getSingleton(service)); - } + /** + * Get List of implementers. + * + * @return the sorted list of services implementing interface 'T' discovered + * by 'ServiceLoader'. + */ + public synchronized List<T> getList() { + if (implementers == null) { + rebuildList(); + } + return implementers; + } - // Sort the list according to sequence number, and then alphabetically - // according to full class name. - Collections.sort(tmp, (o1, o2) -> { - int s1 = o1.getSequenceNumber(); - int s2 = o2.getSequenceNumber(); - if (s1 < s2) { - return -1; - } else if (s1 > s2) { - return 1; - } else { - return o1.getClass().getName().compareTo(o2.getClass().getName()); - } - }); + /** + * This method is called by 'getList', but could also be called directly if + * we were running with a 'ClassLoader' that supported the dynamic addition + * of JAR files. In this case, it could be invoked in order to discover any + * new services implementing interface 'T'. This is probably a relatively + * expensive operation in terms of CPU and elapsed time, so it is best if it + * isn't invoked too frequently. + * + * @return the sorted list of services implementing interface 'T' discovered + * by 'ServiceLoader'. + */ + @SuppressWarnings("unchecked") + public synchronized List<T> rebuildList() { + // build a list of all of the current implementors + List<T> tmp = new LinkedList<>(); + for (T service : serviceLoader) { + tmp.add((T)getSingleton(service)); + } - // create an unmodifiable version of this list - implementers = Collections.unmodifiableList(tmp); - logger.info("***** OrderedServiceImpl implementers:\n {}", implementers); - return implementers; - } + // Sort the list according to sequence number, and then alphabetically + // according to full class name. + Collections.sort(tmp, (o1, o2) -> { + int s1 = o1.getSequenceNumber(); + int s2 = o2.getSequenceNumber(); + if (s1 < s2) { + return -1; + } else if (s1 > s2) { + return 1; + } else { + return o1.getClass().getName().compareTo(o2.getClass().getName()); + } + }); - /** - * If a service implements multiple APIs managed by 'ServiceLoader', a - * separate instance is created for each API. This method ensures that - * the first instance is used in all of the lists. - * - * @param service this is the object created by ServiceLoader - * @return the object to use in place of 'service'. If 'service' is the first - * object of this class created by ServiceLoader, it is returned. If not, - * the object of this class that was initially created is returned - * instead. - */ - private static synchronized OrderedService - getSingleton(OrderedService service) - { - // see if we already have an instance of this class - OrderedService rval = classToSingleton.get(service.getClass()); - if (rval == null) - { - // No previous instance of this class exists -- use the supplied - // instance, and place it in the table. - rval = service; - classToSingleton.put(service.getClass(), service); - } - return rval; - } + // create an unmodifiable version of this list + implementers = Collections.unmodifiableList(tmp); + logger.info("***** OrderedServiceImpl implementers:\n {}", implementers); + return implementers; + } + + /** + * If a service implements multiple APIs managed by 'ServiceLoader', a + * separate instance is created for each API. This method ensures that + * the first instance is used in all of the lists. + * + * @param service this is the object created by ServiceLoader + * @return the object to use in place of 'service'. If 'service' is the first + * object of this class created by ServiceLoader, it is returned. If not, + * the object of this class that was initially created is returned + * instead. + */ + private static synchronized OrderedService getSingleton(OrderedService service) { + // see if we already have an instance of this class + OrderedService rval = classToSingleton.get(service.getClass()); + if (rval == null) { + // No previous instance of this class exists -- use the supplied + // instance, and place it in the table. + rval = service; + classToSingleton.put(service.getClass(), service); + } + return rval; + } } diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/Pair.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/Pair.java index ee0bb6f6..d044ca6f 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/Pair.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/Pair.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-utils * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,31 +21,43 @@ package org.onap.policy.drools.utils; public class Pair<F,S> { - + protected F first; protected S second; - public Pair(F first, S second){ + public Pair(F first, S second) { this.first = first; this.second = second; } - - public F first() {return this.first;} - - public S second() {return this.second;} - - public F getFirst() {return this.first;} - public S getSecond() {return this.second;} - - public void first(F first) {this.first = first;} - - public void second(S second) {this.second = second;} - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("Pair [first=").append(first).append(", second=").append(second).append("]"); - return builder.toString(); - } + public F first() { + return this.first; + } + + public void first(F first) { + this.first = first; + } + + public S second() { + return this.second; + } + + public void second(S second) { + this.second = second; + } + + public F getFirst() { + return this.first; + } + + public S getSecond() { + return this.second; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Pair [first=").append(first).append(", second=").append(second).append("]"); + return builder.toString(); + } } diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java index 4e00a6db..c0014f4d 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-utils * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,357 +36,323 @@ import org.slf4j.LoggerFactory; /** * This class provides utilities to read properties from a properties - * file, and optionally get notifications of future changes + * file, and optionally get notifications of future changes. */ -public class PropertyUtil -{ - - // timer thread used for polling for property file changes - private static Timer timer = null; - - // this table maps canonical file into a 'ListenerRegistration' instance - private static HashMap<File, ListenerRegistration> registrations = - new HashMap<>(); - - private static final Logger logger = LoggerFactory.getLogger(PropertyUtil.class.getName()); - - /** - * Read in a properties file - * @param file the properties file - * @return a Properties object, containing the associated properties - * @throws IOException - subclass 'FileNotFoundException' if the file - * does not exist or can't be opened, and 'IOException' if there is - * a problem loading the properties file. - */ - public static Properties getProperties(File file) throws IOException - { - // create an InputStream (may throw a FileNotFoundException) - FileInputStream fis = new FileInputStream(file); - try - { - // create the properties instance - Properties rval = new Properties(); - - // load properties (may throw an IOException) - rval.load(fis); - return rval; - } - finally - { - // close input stream - fis.close(); - } - } - - /** - * Read in a properties file - * @param fileName the properties file - * @return a Properties object, containing the associated properties - * @throws IOException - subclass 'FileNotFoundException' if the file - * does not exist or can't be opened, and 'IOException' if there is - * a problem loading the properties file. - */ - public static Properties getProperties(String fileName) throws IOException - { - return getProperties(new File(fileName)); - } - - /* ============================================================ */ - - /** - * This is the callback interface, used for sending notifications of - * changes in the properties file. - */ - @FunctionalInterface - public interface Listener - { - /** - * Notification of a properties file change - * @param properties the new properties - * @param the set of property names that have changed, including - * additions and removals - */ - void propertiesChanged(Properties properties, Set<String> changedKeys); - } - - /** - * This is an internal class - one instance of this exists for each - * property file that is being monitored. Note that multiple listeners - * can be registered for the same file. - */ - private static class ListenerRegistration - { - // the canonical path of the file being monitored - File file; - - // the most recent value of 'file.lastModified()' - long lastModified; - - // the most recent set of properties - Properties properties; - - // the set of listeners monitoring this file - LinkedList<Listener> listeners; - - // the 'TimerTask' instance, used for periodic polling - TimerTask timerTask; - - /** - * Constructor - create a 'ListenerRegistration' instance for this - * file, but with no listeners - */ - ListenerRegistration(File file) throws IOException - { - this.file = file; - - // The initial value of 'lastModified' is set to 0 to ensure that we - // correctly handle the case where the file is modified within the - // same second that polling begins. - lastModified = 0; - - // fetch current properties - properties = getProperties(file); - - // no listeners yet - listeners = new LinkedList<>(); - - // add to static table, so this instance can be shared - registrations.put(file, this); - - // still need to create a timer thread - synchronized(PropertyUtil.class) - { - // an additional check is added inside the 'synchronized' block, - // just in case someone beat us to it - if (timer == null) - { - timer = new Timer("PropertyUtil-Timer", true); - } - } - - // create and schedule the timer task, so this is periodically polled - timerTask = new TimerTask() - { - @Override - public void run() - { - try - { - poll(); - } - catch (Exception e) - { - logger.warn("Polling for property changes", e); - } - } - }; - timer.schedule(timerTask, 10000L, 10000L); - } - - /** - * Add a listener to the notification list - * @param listener this is the listener to add to the list - * @return the properties at the moment the listener was added to the list - */ - synchronized Properties addListener(Listener listener) - { - listeners.add(listener); - return (Properties)properties.clone(); - } - - /** - * Remove a listener from the notification list - * @param listener this is the listener to remove - */ - synchronized void removeListener(Listener listener) - { - listeners.remove(listener); - - // See if we need to remove this 'ListenerRegistration' instance - // from the table. The 'synchronized' block is needed in case - // another listener is being added at about the same time that this - // one is being removed. - synchronized(registrations) - { - if (listeners.isEmpty()) - { - timerTask.cancel(); - registrations.remove(file); - } - } - } - - /** - * This method is periodically called to check for property list updates - * @throws IOException if there is an error in reading the properties file - */ - synchronized void poll() throws IOException - { - long timestamp = file.lastModified(); - if (timestamp != lastModified) - { - // update the record, and send out the notifications - lastModified = timestamp; - - // Save old set, and initial set of changed properties. - Properties oldProperties = properties; - HashSet<String> changedProperties = - new HashSet<>(oldProperties.stringPropertyNames()); - - // Fetch the list of listeners that we will potentially notify, - // and the new properties. Note that this is in a 'synchronized' - // block to ensure that all listeners receiving notifications - // actually have a newer list of properties than the one - // returned on the initial 'getProperties' call. - properties = getProperties(file); - - Set<String> newPropertyNames = properties.stringPropertyNames(); - changedProperties.addAll(newPropertyNames); - - // At this point, 'changedProperties' is the union of all properties - // in both the old and new properties files. Iterate through all - // of the entries in the new properties file - if the entry - // matches the one in the old file, remove it from - // 'changedProperties'. - for (String name : newPropertyNames) - { - if (properties.getProperty(name).equals - (oldProperties.getProperty(name))) - { - // Apparently, any property that exists must be of type - // 'String', and can't be null. For this reason, we don't - // need to worry about the case where - // 'properties.getProperty(name)' returns 'null'. Note that - // 'oldProperties.getProperty(name)' may be 'null' if the - // old property does not exist. - changedProperties.remove(name); - } - } - - // 'changedProperties' should be correct at this point - if (!changedProperties.isEmpty()) - { - // there were changes - notify everyone in 'listeners' - for (final Listener notify : listeners) - { - // Copy 'properties' and 'changedProperties', so it doesn't - // cause problems if the recipient makes changes. - final Properties tmpProperties = - (Properties)(properties.clone()); - final HashSet<String> tmpChangedProperties = - new HashSet<>(changedProperties); - - // Do the notification in a separate thread, so blocking - // won't cause any problems. - new Thread() - { - @Override - public void run() - { - notify.propertiesChanged - (tmpProperties, tmpChangedProperties); - } - }.start(); - } - } - } - } - } - - /** - * Read in a properties file, and register for update notifications. - * NOTE: it is possible that the first callback will occur while this - * method is still in progress. To avoid this problem, use 'synchronized' - * blocks around this invocation and in the callback -- that will ensure - * that the processing of the initial properties complete before any - * updates are processed. - * - * @param file the properties file - * @param notify if not null, this is a callback interface that is used for - * notifications of changes - * @return a Properties object, containing the associated properties - * @throws IOException - subclass 'FileNotFoundException' if the file - * does not exist or can't be opened, and 'IOException' if there is - * a problem loading the properties file. - */ - public static Properties getProperties(File file, Listener listener) - throws IOException - { - File propFile = file; - if (listener == null) - { - // no listener specified -- just fetch the properties - return getProperties(propFile); - } - - // Convert the file to a canonical form in order to avoid the situation - // where different names refer to the same file. - propFile = propFile.getCanonicalFile(); - - // See if there is an existing registration. The 'synchronized' block - // is needed to handle the case where a new listener is added at about - // the same time that another one is being removed. - synchronized(registrations) - { - ListenerRegistration reg = registrations.get(propFile); - if (reg == null) - { - // a new registration is needed - reg = new ListenerRegistration(propFile); - } - return reg.addListener(listener); - } - } - - /** - * Read in a properties file, and register for update notifications. - * NOTE: it is possible that the first callback will occur while this - * method is still in progress. To avoid this problem, use 'synchronized' - * blocks around this invocation and in the callback -- that will ensure - * that the processing of the initial properties complete before any - * updates are processed. - * - * @param fileName the properties file - * @param notify if not null, this is a callback interface that is used for - * notifications of changes - * @return a Properties object, containing the associated properties - * @throws IOException - subclass 'FileNotFoundException' if the file - * does not exist or can't be opened, and 'IOException' if there is - * a problem loading the properties file. - */ - public static Properties getProperties(String fileName, Listener listener) - throws IOException - { - return getProperties(new File(fileName), listener); - } - - /** - * Stop listenening for updates - * @param file the properties file - * @param notify if not null, this is a callback interface that was used for - * notifications of changes - */ - public static void stopListening(File file, Listener listener) - { - if (listener != null) - { - ListenerRegistration reg = registrations.get(file); - if (reg != null) - { - reg.removeListener(listener); - } - } - } - - /** - * Stop listenening for updates - * @param fileName the properties file - * @param notify if not null, this is a callback interface that was used for - * notifications of changes - */ - public static void stopListening(String fileName, Listener listener) - { - stopListening(new File(fileName), listener); - } +public class PropertyUtil { + + // timer thread used for polling for property file changes + private static Timer timer = null; + + // this table maps canonical file into a 'ListenerRegistration' instance + private static HashMap<File, ListenerRegistration> registrations = + new HashMap<>(); + + private static final Logger logger = LoggerFactory.getLogger(PropertyUtil.class.getName()); + + /** + * Read in a properties file. + * + * @param file the properties file + * @return a Properties object, containing the associated properties + * @throws IOException - subclass 'FileNotFoundException' if the file + * does not exist or can't be opened, and 'IOException' if there is + * a problem loading the properties file. + */ + public static Properties getProperties(File file) throws IOException { + // create an InputStream (may throw a FileNotFoundException) + try (FileInputStream fis = new FileInputStream(file)) { + // create the properties instance + Properties rval = new Properties(); + + // load properties (may throw an IOException) + rval.load(fis); + return rval; + } + } + + /** + * Read in a properties file. + * + * @param fileName the properties file + * @return a Properties object, containing the associated properties + * @throws IOException - subclass 'FileNotFoundException' if the file + * does not exist or can't be opened, and 'IOException' if there is + * a problem loading the properties file. + */ + public static Properties getProperties(String fileName) throws IOException { + return getProperties(new File(fileName)); + } + + /* ============================================================ */ + + /** + * This is the callback interface, used for sending notifications of + * changes in the properties file. + */ + @FunctionalInterface + public interface Listener { + /** + * Notification of a properties file change. + * + * @param properties the new properties + * @param changedKeys the set of property names that have changed, including + * additions and removals + */ + void propertiesChanged(Properties properties, Set<String> changedKeys); + } + + /** + * This is an internal class - one instance of this exists for each + * property file that is being monitored. Note that multiple listeners + * can be registered for the same file. + */ + private static class ListenerRegistration { + // the canonical path of the file being monitored + File file; + + // the most recent value of 'file.lastModified()' + long lastModified; + + // the most recent set of properties + Properties properties; + + // the set of listeners monitoring this file + LinkedList<Listener> listeners; + + // the 'TimerTask' instance, used for periodic polling + TimerTask timerTask; + + /** + * Constructor - create a 'ListenerRegistration' instance for this + * file, but with no listeners. + */ + ListenerRegistration(File file) throws IOException { + this.file = file; + + // The initial value of 'lastModified' is set to 0 to ensure that we + // correctly handle the case where the file is modified within the + // same second that polling begins. + lastModified = 0; + + // fetch current properties + properties = getProperties(file); + + // no listeners yet + listeners = new LinkedList<>(); + + // add to static table, so this instance can be shared + registrations.put(file, this); + + // still need to create a timer thread + synchronized (PropertyUtil.class) { + // an additional check is added inside the 'synchronized' block, + // just in case someone beat us to it + if (timer == null) { + timer = new Timer("PropertyUtil-Timer", true); + } + } + + // create and schedule the timer task, so this is periodically polled + timerTask = new TimerTask() { + @Override + public void run() { + try { + poll(); + } + catch (Exception e) { + logger.warn("Polling for property changes", e); + } + } + }; + timer.schedule(timerTask, 10000L, 10000L); + } + + /** + * Add a listener to the notification list. + * + * @param listener this is the listener to add to the list + * @return the properties at the moment the listener was added to the list + */ + synchronized Properties addListener(Listener listener) { + listeners.add(listener); + return (Properties)properties.clone(); + } + + /** + * Remove a listener from the notification list. + * + * @param listener this is the listener to remove + */ + synchronized void removeListener(Listener listener) { + listeners.remove(listener); + + // See if we need to remove this 'ListenerRegistration' instance + // from the table. The 'synchronized' block is needed in case + // another listener is being added at about the same time that this + // one is being removed. + synchronized (registrations) { + if (listeners.isEmpty()) { + timerTask.cancel(); + registrations.remove(file); + } + } + } + + /** + * This method is periodically called to check for property list updates. + * + * @throws IOException if there is an error in reading the properties file + */ + synchronized void poll() throws IOException { + long timestamp = file.lastModified(); + if (timestamp != lastModified) { + // update the record, and send out the notifications + lastModified = timestamp; + + // Save old set, and initial set of changed properties. + Properties oldProperties = properties; + HashSet<String> changedProperties = + new HashSet<>(oldProperties.stringPropertyNames()); + + // Fetch the list of listeners that we will potentially notify, + // and the new properties. Note that this is in a 'synchronized' + // block to ensure that all listeners receiving notifications + // actually have a newer list of properties than the one + // returned on the initial 'getProperties' call. + properties = getProperties(file); + + Set<String> newPropertyNames = properties.stringPropertyNames(); + changedProperties.addAll(newPropertyNames); + + // At this point, 'changedProperties' is the union of all properties + // in both the old and new properties files. Iterate through all + // of the entries in the new properties file - if the entry + // matches the one in the old file, remove it from + // 'changedProperties'. + for (String name : newPropertyNames) { + if (properties.getProperty(name).equals(oldProperties.getProperty(name))) { + // Apparently, any property that exists must be of type + // 'String', and can't be null. For this reason, we don't + // need to worry about the case where + // 'properties.getProperty(name)' returns 'null'. Note that + // 'oldProperties.getProperty(name)' may be 'null' if the + // old property does not exist. + changedProperties.remove(name); + } + } + + // 'changedProperties' should be correct at this point + if (!changedProperties.isEmpty()) { + // there were changes - notify everyone in 'listeners' + for (final Listener notify : listeners) { + // Copy 'properties' and 'changedProperties', so it doesn't + // cause problems if the recipient makes changes. + final Properties tmpProperties = + (Properties)(properties.clone()); + final HashSet<String> tmpChangedProperties = + new HashSet<>(changedProperties); + + // Do the notification in a separate thread, so blocking + // won't cause any problems. + new Thread() { + @Override + public void run() { + notify.propertiesChanged(tmpProperties, tmpChangedProperties); + } + }.start(); + } + } + } + } + } + + /** + * Read in a properties file, and register for update notifications. + * NOTE: it is possible that the first callback will occur while this + * method is still in progress. To avoid this problem, use 'synchronized' + * blocks around this invocation and in the callback -- that will ensure + * that the processing of the initial properties complete before any + * updates are processed. + * + * @param file the properties file + * @param listener notify if not null, this is a callback interface that is used for + * notifications of changes + * @return a Properties object, containing the associated properties + * @throws IOException - subclass 'FileNotFoundException' if the file + * does not exist or can't be opened, and 'IOException' if there is + * a problem loading the properties file. + */ + public static Properties getProperties(File file, Listener listener) + throws IOException { + File propFile = file; + if (listener == null) { + // no listener specified -- just fetch the properties + return getProperties(propFile); + } + + // Convert the file to a canonical form in order to avoid the situation + // where different names refer to the same file. + propFile = propFile.getCanonicalFile(); + + // See if there is an existing registration. The 'synchronized' block + // is needed to handle the case where a new listener is added at about + // the same time that another one is being removed. + synchronized (registrations) { + ListenerRegistration reg = registrations.get(propFile); + if (reg == null) { + // a new registration is needed + reg = new ListenerRegistration(propFile); + } + return reg.addListener(listener); + } + } + + /** + * Read in a properties file, and register for update notifications. + * NOTE: it is possible that the first callback will occur while this + * method is still in progress. To avoid this problem, use 'synchronized' + * blocks around this invocation and in the callback -- that will ensure + * that the processing of the initial properties complete before any + * updates are processed. + * + * @param fileName the properties file + * @param listener notify if not null, this is a callback interface that is used for + * notifications of changes + * @return a Properties object, containing the associated properties + * @throws IOException - subclass 'FileNotFoundException' if the file + * does not exist or can't be opened, and 'IOException' if there is + * a problem loading the properties file. + */ + public static Properties getProperties(String fileName, Listener listener) + throws IOException { + return getProperties(new File(fileName), listener); + } + + /** + * Stop listenening for updates. + * + * @param file the properties file + * @param listener notify if not null, this is a callback interface that was used for + * notifications of changes + */ + public static void stopListening(File file, Listener listener) { + if (listener != null) { + ListenerRegistration reg = registrations.get(file); + if (reg != null) { + reg.removeListener(listener); + } + } + } + + /** + * Stop listenening for updates. + * + * @param fileName the properties file + * @param listener notify if not null, this is a callback interface that was used for + * notifications of changes + */ + public static void stopListening(String fileName, Listener listener) { + stopListening(new File(fileName), listener); + } } diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/Reference.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/Reference.java index 0c4155fe..7755177e 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/Reference.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/Reference.java @@ -30,14 +30,17 @@ public class Reference<T> { private T value; /** + * Constructor. * - * @param value + * @param value value */ public Reference(T value) { this.value = value; } /** + * Get the value. + * * @return the current value */ public final T get() { @@ -47,7 +50,7 @@ public class Reference<T> { /** * Sets the reference to point to a new value. * - * @param newValue + * @param newValue the new value */ public final void set(T newValue) { this.value = newValue; @@ -56,8 +59,8 @@ public class Reference<T> { /** * Sets the value to a new value, if the value is currently the same as the old value. * - * @param oldValue - * @param newValue + * @param oldValue old value + * @param newValue new value * @return {@code true} if the value was updated, {@code false} otherwise */ public boolean compareAndSet(T oldValue, T newValue) { diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/ReflectionUtil.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/ReflectionUtil.java index bf59ec96..f618b4c9 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/ReflectionUtil.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/ReflectionUtil.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-utils * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,66 +21,72 @@ /** * */ + package org.onap.policy.drools.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + /** - * Reflection utilities + * Reflection utilities. * */ public class ReflectionUtil { - - protected static final Logger logger = LoggerFactory.getLogger(ReflectionUtil.class); - private ReflectionUtil(){ - } - - /** - * returns (if exists) a class fetched from a given classloader - * - * @param classLoader the class loader - * @param className the class name - * @return the actual class - * @throws IllegalArgumentException if an invalid parameter has been passed in - */ - public static Class<?> fetchClass(ClassLoader classLoader, - String className) { - if (classLoader == null) - throw new IllegalArgumentException("A class loader must be provided"); - - if (className == null) - throw new IllegalArgumentException("A class name to be fetched in class loader " + - classLoader + " must be provided"); - - try { - return Class.forName(className, true, classLoader); - } catch (Exception e) { - logger.error("class {} fetched in {} does not exist", className, classLoader, e); - } - - return null; - } - - /** - * - * @param classLoader target class loader - * @param classname class name to fetch - * @return true if exists - * @throws IllegalArgumentException if an invalid parameter has been passed in - */ - public static boolean isClass(ClassLoader classLoader, String classname) { - return fetchClass(classLoader, classname) != null; - } - - /** - * is a subclass? - * @param parent superclass - * @param presumedSubclass subclass - * @return - */ - public static boolean isSubclass(Class<?> parent, Class<?> presumedSubclass) { - return parent.isAssignableFrom(presumedSubclass); - } + protected static final Logger logger = LoggerFactory.getLogger(ReflectionUtil.class); + + private ReflectionUtil(){ + } + + /** + * returns (if exists) a class fetched from a given classloader. + * + * @param classLoader the class loader + * @param className the class name + * @return the actual class + * @throws IllegalArgumentException if an invalid parameter has been passed in + */ + public static Class<?> fetchClass(ClassLoader classLoader, + String className) { + if (classLoader == null) { + throw new IllegalArgumentException("A class loader must be provided"); + } + + if (className == null) { + throw new IllegalArgumentException("A class name to be fetched in class loader " + + classLoader + " must be provided"); + } + + try { + return Class.forName(className, true, classLoader); + } catch (Exception e) { + logger.error("class {} fetched in {} does not exist", className, classLoader, e); + } + + return null; + } + + /** + * Is class. + * + * @param classLoader target class loader + * @param classname class name to fetch + * @return true if exists + * @throws IllegalArgumentException if an invalid parameter has been passed in + */ + public static boolean isClass(ClassLoader classLoader, String classname) { + return fetchClass(classLoader, classname) != null; + } + + /** + * Is it a sub class. + * + * @param parent superclass + * @param presumedSubclass subclass + * @return + */ + public static boolean isSubclass(Class<?> parent, Class<?> presumedSubclass) { + return parent.isAssignableFrom(presumedSubclass); + } } diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/Triple.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/Triple.java index 66179aa2..04817346 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/Triple.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/Triple.java @@ -21,7 +21,7 @@ package org.onap.policy.drools.utils; public class Triple<F,S,T> { - + private F first; private S second; private T third; @@ -30,24 +30,31 @@ public class Triple<F,S,T> { // empty constructor } - public Triple(F first, S second, T third){ + /** + * Constructor. + * + * @param first first + * @param second second + * @param third third + */ + public Triple(F first, S second, T third) { this.first = first; this.second = second; this.third = third; } - public F first(){ + public F first() { return this.getFirst(); } - public F getFirst() { - return first; - } - public void first(F first) { this.setFirst(first); } + public F getFirst() { + return first; + } + public void setFirst(F first) { this.first = first; } @@ -56,14 +63,14 @@ public class Triple<F,S,T> { return this.getSecond(); } - public S getSecond() { - return second; - } - public void second(S second) { this.setSecond(second); } + public S getSecond() { + return second; + } + public void setSecond(S second) { this.second = second; } @@ -72,14 +79,14 @@ public class Triple<F,S,T> { return this.getThird(); } - public T getThird() { - return this.third; - } - public void third(T third) { this.setThird(third); } + public T getThird() { + return this.third; + } + public void setThird(T third) { this.third = third; } diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerMarkerFilter.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerMarkerFilter.java index 19414d31..e15dae0d 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerMarkerFilter.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerMarkerFilter.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.policy.drools.utils.logging; import ch.qos.logback.classic.spi.ILoggingEvent; @@ -33,7 +34,7 @@ public abstract class LoggerMarkerFilter extends AbstractMatcherFilter<ILoggingE protected final Marker marker; public LoggerMarkerFilter(Marker marker) { - this.marker = marker; + this.marker = marker; } @Override @@ -55,7 +56,7 @@ public abstract class LoggerMarkerFilter extends AbstractMatcherFilter<ILoggingE } /** - * Metric Logger Marker Filter + * Metric Logger Marker Filter. */ public static class MetricLoggerMarkerFilter extends LoggerMarkerFilter { @@ -66,7 +67,7 @@ public abstract class LoggerMarkerFilter extends AbstractMatcherFilter<ILoggingE } /** - * Transaction Logger Marker Filter + * Transaction Logger Marker Filter. */ public static class TransactionLoggerMarkerFilter extends LoggerMarkerFilter { diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerUtil.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerUtil.java index 26b35702..0fe848c9 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerUtil.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerUtil.java @@ -17,41 +17,41 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.policy.drools.utils.logging; -import org.slf4j.LoggerFactory; +package org.onap.policy.drools.utils.logging; import ch.qos.logback.classic.LoggerContext; +import org.slf4j.LoggerFactory; import org.slf4j.Marker; import org.slf4j.MarkerFactory; /** - * Loger Utils + * Loger Utils. */ public class LoggerUtil { /** - * Root logger + * Root logger. */ public static final String ROOT_LOGGER = "ROOT"; /** - * Metric Log Marker Name + * Metric Log Marker Name. */ public static final String METRIC_LOG_MARKER_NAME = "metric"; /** - * Transaction Log Marker Name + * Transaction Log Marker Name. */ public static final String TRANSACTION_LOG_MARKER_NAME = "transaction"; /** - * Marks a logging record as a metric + * Marks a logging record as a metric. */ public static final Marker METRIC_LOG_MARKER = MarkerFactory.getMarker(METRIC_LOG_MARKER_NAME); /** - * Marks a logging record as an end-to-end transaction + * Marks a logging record as an end-to-end transaction. */ public static final Marker TRANSACTION_LOG_MARKER = MarkerFactory.getMarker(TRANSACTION_LOG_MARKER_NAME); @@ -61,7 +61,7 @@ public class LoggerUtil { } /** - * set the log level of a logger + * Set the log level of a logger. * * @param loggerName logger name * @param loggerLevel logger level diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/MDCTransaction.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/MDCTransaction.java index 39fbe8fb..c6e78b28 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/MDCTransaction.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/MDCTransaction.java @@ -33,28 +33,28 @@ import org.slf4j.MDC; /** * MDC Transaction Utility Class. * - * There is an implicit 2-level tree of Transactions in ONAP: transactions and subtransactions. + * <p>There is an implicit 2-level tree of Transactions in ONAP: transactions and subtransactions. * - * 1. The top level transaction relates to the overarching transaction id (ie. RequestId) and should + * <p>1. The top level transaction relates to the overarching transaction id (ie. RequestId) and should * be made available to subtransactions for reuse in the ThreadLocal MDC structure. * - * This is the data to be inherited and common to all subtransactions (not a common case but could + * <p>This is the data to be inherited and common to all subtransactions (not a common case but could * be modified by subtransactions): * - * Request ID Virtual Server Name Partner Name Server Server IP Address Server FQDN + * <p>Request ID Virtual Server Name Partner Name Server Server IP Address Server FQDN * - * 2. The second level at the leaves is formed by subtransactions and the key identifier is the + * <p>2. The second level at the leaves is formed by subtransactions and the key identifier is the * invocation id. * - * Begin Timestamp End Timestamp Elapsed Time Service Instance ID Service Name Status Code Response + * <p>Begin Timestamp End Timestamp Elapsed Time Service Instance ID Service Name Status Code Response * Code Response Description Instance UUID Severity Target Entity Target Service Name Server Server * IP Address Server FQDN Client IP Address Process Key Remote Host Alert Severity Target Virtual * Entity * * - * The naming convention for the fields must match the naming given at + * <p>The naming convention for the fields must match the naming given at * - * https://wiki.onap.org/pages/viewpage.action?pageId=20087036 + * <p>https://wiki.onap.org/pages/viewpage.action?pageId=20087036 */ public interface MDCTransaction { /* @@ -184,42 +184,42 @@ public interface MDCTransaction { String TARGET_VIRTUAL_ENTITY = "TargetVirtualEntity"; /** - * Default Service Name + * Default Service Name. */ String DEFAULT_SERVICE_NAME = "PDP-D"; /** - * Default Host Name + * Default Host Name. */ String DEFAULT_HOSTNAME = NetworkUtil.getHostname(); /** - * Default Host IP + * Default Host IP. */ String DEFAULT_HOSTIP = NetworkUtil.getHostIp(); /** - * Status Code Complete + * Status Code Complete. */ String STATUS_CODE_COMPLETE = "COMPLETE"; /** - * Status Code Error + * Status Code Error. */ String STATUS_CODE_FAILURE = "ERROR"; /** - * reset subtransaction data + * reset subtransaction data. */ MDCTransaction resetSubTransaction(); /** - * resets transaction data + * resets transaction data. */ MDCTransaction resetTransaction(); /** - * flush to MDC structure + * flush to MDC structure. */ MDCTransaction flush(); @@ -236,102 +236,102 @@ public interface MDCTransaction { MDCTransaction transaction(); /** - * get invocation id + * get invocation id. */ MDCTransaction setInvocationId(String invocationId); /** - * set start time + * set start time. */ MDCTransaction setStartTime(Instant startTime); /** - * set service name + * set service name. */ MDCTransaction setServiceName(String serviceName); /** - * set status code + * set status code. */ MDCTransaction setStatusCode(String statusCode); /** - * set status code + * set status code. */ MDCTransaction setStatusCode(boolean success); /** - * sets response code + * sets response code. */ MDCTransaction setResponseCode(String responseCode); /** - * sets response description + * sets response description. */ MDCTransaction setResponseDescription(String responseDescription); /** - * sets instance uuid + * sets instance uuid. */ MDCTransaction setInstanceUUID(String instanceUUID); /** - * set severity + * set severity. */ MDCTransaction setSeverity(String severity); /** - * set target entity + * set target entity. */ MDCTransaction setTargetEntity(String targetEntity); /** - * set target service name + * set target service name. */ MDCTransaction setTargetServiceName(String targetServiceName); /** - * set target virtual entity + * set target virtual entity. */ MDCTransaction setTargetVirtualEntity(String targetVirtualEntity); /** - * set request id + * set request id. */ MDCTransaction setRequestId(String requestId); /** - * set partner + * set partner. */ MDCTransaction setPartner(String partner); /** - * set server + * set server. */ MDCTransaction setServer(String server); /** - * set server ip address + * set server ip address. */ MDCTransaction setServerIpAddress(String serverIpAddress); /** - * set server fqdn + * set server fqdn. */ MDCTransaction setServerFqdn(String serverFqdn); /** - * set virtual server + * set virtual server. */ MDCTransaction setVirtualServerName(String virtualServerName); /** - * sets end time + * sets end time. */ MDCTransaction setEndTime(Instant endTime); /** - * sets elapsed time + * sets elapsed time. */ MDCTransaction setElapsedTime(Long elapsedTime); @@ -341,152 +341,152 @@ public interface MDCTransaction { MDCTransaction setServiceInstanceId(String serviceInstanceId); /** - * sets process key + * sets process key. */ MDCTransaction setProcessKey(String processKey); /** - * sets alert severity + * sets alert severity. */ MDCTransaction setAlertSeverity(String alertSeverity); /** - * sets client ip address + * sets client ip address. */ MDCTransaction setClientIpAddress(String clientIpAddress); /** - * sets remote host + * sets remote host. */ MDCTransaction setRemoteHost(String remoteHost); /** - * get start time + * get start time. */ Instant getStartTime(); /** - * get server + * get server. */ String getServer(); /** - * get end time + * get end time. */ Instant getEndTime(); /** - * get elapsed time + * get elapsed time. */ Long getElapsedTime(); /** - * get remote host + * get remote host. */ String getRemoteHost(); /** - * get client ip address + * get client ip address. */ String getClientIpAddress(); /** - * get alert severity + * get alert severity. */ String getAlertSeverity(); /** - * get process key + * get process key. */ String getProcessKey(); /** - * get service instance id + * get service instance id. */ String getServiceInstanceId(); /** - * get invocation id + * get invocation id. */ String getInvocationId(); /** - * get service name + * get service name. */ String getServiceName(); /** - * get status code + * get status code. */ String getStatusCode(); /** - * get response description + * get response description. */ String getResponseDescription(); /** - * get instance uuid + * get instance uuid. */ String getInstanceUUID(); /** - * get severity + * get severity. */ String getSeverity(); /** - * get target entity + * get target entity. */ String getTargetEntity(); /** - * get service name + * get service name. */ String getTargetServiceName(); /** - * get target virtual entity + * get target virtual entity. */ String getTargetVirtualEntity(); /** - * get response code + * get response code. */ String getResponseCode(); /** - * get request id + * get request id. */ String getRequestId(); /** - * get partner + * get partner. */ String getPartner(); /** - * get server fqdn + * get server fqdn. */ String getServerFqdn(); /** - * get virtual server name + * get virtual server name. */ String getVirtualServerName(); /** - * get server ip + * get server ip. */ String getServerIpAddress(); /** - * generate timestamp used for logging + * generate timestamp used for logging. */ String timestamp(Instant time); /** - * create new MDC Transaction + * create new MDC Transaction. * * @param requestId transaction Id * @param partner requesting partner @@ -498,14 +498,14 @@ public interface MDCTransaction { } /** - * create new MDC Transaction + * create new MDC Transaction. */ static MDCTransaction newTransaction() { return new MDCTransactionImpl(); } /** - * create new subtransaction + * create new subtransaction. * * @param invocationId sub-transaction od * @return MDC Transaction @@ -515,7 +515,7 @@ public interface MDCTransaction { } /** - * create transaction from an existing one + * create transaction from an existing one. * * @param transaction transaction * @return MDC Transaction @@ -529,10 +529,10 @@ public interface MDCTransaction { class MDCTransactionImpl implements MDCTransaction { - private final static Logger logger = LoggerFactory.getLogger(MDCTransactionImpl.class.getName()); + private static final Logger logger = LoggerFactory.getLogger(MDCTransactionImpl.class.getName()); /** - * Logging Format for Timestamps + * Logging Format for Timestamps. */ private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS+00:00"; @@ -571,14 +571,14 @@ class MDCTransactionImpl implements MDCTransaction { private String remoteHost; /** - * Transaction with no information set + * Transaction with no information set. */ public MDCTransactionImpl() { MDC.clear(); } /** - * MDC Transaction + * MDC Transaction. * * @param requestId transaction id * @param partner transaction origin @@ -599,7 +599,7 @@ class MDCTransactionImpl implements MDCTransaction { } /** - * create subtransaction + * create subtransaction. * * @param invocationId subtransaction id */ @@ -619,9 +619,9 @@ class MDCTransactionImpl implements MDCTransaction { } /** - * copy constructor transaction/subtransaction + * copy constructor transaction/subtransaction. * - * @param transaction + * @param transaction transaction */ public MDCTransactionImpl(MDCTransaction transaction) { MDC.clear(); @@ -652,7 +652,7 @@ class MDCTransactionImpl implements MDCTransaction { } /** - * reset subtransaction portion + * reset subtransaction portion. * * @return MDCTransaction */ @@ -685,7 +685,7 @@ class MDCTransactionImpl implements MDCTransaction { } /** - * flush transaction to MDC + * flush transaction to MDC. */ @Override public MDCTransaction flush() { @@ -971,11 +971,11 @@ class MDCTransactionImpl implements MDCTransaction { } @Override - public MDCTransaction setInstanceUUID(String instanceUUID) { - if (instanceUUID == null) { + public MDCTransaction setInstanceUUID(String instanceUuid) { + if (instanceUuid == null) { this.instanceUUID = UUID.randomUUID().toString(); } else { - this.instanceUUID = instanceUUID; + this.instanceUUID = instanceUuid; } MDC.put(INSTANCE_UUID, this.instanceUUID); diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/PairTripleTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/PairTripleTest.java index 5063447c..fa8a62c8 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/PairTripleTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/PairTripleTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-utils * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,40 +29,40 @@ public class PairTripleTest { @Test public void pairTest() { - Pair<String, String> p = new Pair<String, String>("foo", "bar"); + Pair<String, String> pair = new Pair<String, String>("foo", "bar"); - assertEquals("foo", p.first()); - assertEquals("bar", p.second()); - assertEquals("foo", p.getFirst()); - assertEquals("bar", p.getSecond()); - - p.first("one"); - p.second("two"); + assertEquals("foo", pair.first()); + assertEquals("bar", pair.second()); + assertEquals("foo", pair.getFirst()); + assertEquals("bar", pair.getSecond()); - assertEquals("one", p.first()); - assertEquals("two", p.second()); - assertEquals("one", p.getFirst()); - assertEquals("two", p.getSecond()); - - assertNotNull(p.toString()); + pair.first("one"); + pair.second("two"); + + assertEquals("one", pair.first()); + assertEquals("two", pair.second()); + assertEquals("one", pair.getFirst()); + assertEquals("two", pair.getSecond()); + + assertNotNull(pair.toString()); } @Test public void tripleTest() { - Triple<String, String, String> t = new Triple<String, String,String>("foo", "bar", "fiz"); + Triple<String, String, String> triple = new Triple<String, String,String>("foo", "bar", "fiz"); - assertEquals("foo", t.first()); - assertEquals("bar", t.second()); - assertEquals("fiz", t.third()); - - t.first("one"); - t.second("two"); - t.third("three"); + assertEquals("foo", triple.first()); + assertEquals("bar", triple.second()); + assertEquals("fiz", triple.third()); + + triple.first("one"); + triple.second("two"); + triple.third("three"); - assertEquals("one", t.first()); - assertEquals("two", t.second()); - assertEquals("three", t.third()); + assertEquals("one", triple.first()); + assertEquals("two", triple.second()); + assertEquals("three", triple.third()); } } diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java index 9d2aa397..05440c69 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-utils * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,165 +37,146 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class PropertyUtilTest -{ - private final static Logger logger = LoggerFactory.getLogger(PropertyUtilTest.class); - - private static File directory = null; - - /** - * Test Setup -- Create a directory for temporary files - */ - @BeforeClass - static public void setup() - { - logger.info("setup: creating a temporary directory"); - - // create a directory for temporary files - directory = new File(UUID.randomUUID().toString()); - directory.mkdir(); - } - - /** - * Test Cleanup -- Remove temporary files - */ - @AfterClass - static public void teardown() - { - logger.info("teardown: remove the temporary directory"); - - // the assumption is that we only have one level of temporary files - for (File file : directory.listFiles()) - { - file.delete(); - } - directory.delete(); - } - - /** - * Utility method to write a properties file - * - * @param name the file name, relative to the temporary directory - * @param the properties to store in the file - * @return a File instance associated with the newly-created file - * @throws IOException if the file can't be created for some reason - */ - File createFile(String name, Properties p) throws IOException - { - File file = new File(directory, name); - FileOutputStream fos = new FileOutputStream(file); - try - { - p.store(fos, "Property file '" + name + "'"); - } - finally - { - fos.close(); - } - return(file); - } - - /** - * Create a 'PropertyUtil.Listener' subclass, which receives property - * file updates. It stores the latest values in an array, and notifies - * any thread waiting on this array. - * - * @param returns this is an array of length 2 -- the first entry will - * contain the 'properties' value, and the second will contain - * 'changedKeys'. It is also used to signal any waiting thread - * using 'returns.notifyAll()'. - */ - PropertyUtil.Listener createListenerThread(final Object[] returns) - { - return(new PropertyUtil.Listener() - { - public void propertiesChanged - (Properties properties, Set<String> changedKeys) - { - // When a notification is received, store the values in the - // 'returns' array, and signal using the same array. - logger.info("Listener invoked: properties=" + properties - + ", changedKeys=" + changedKeys); - returns[0] = properties; - returns[1] = changedKeys; - synchronized(returns) - { - returns.notifyAll(); - } - } - }); - } - - /** - * Test the basic properties file interface. - */ - @Test - public void testGetProperties() throws Exception - { - logger.info("testGetProperties: test the basic properties file interface"); - - // copy system properties - logger.info("Copy system properties to a file"); - Properties prop1 = System.getProperties(); - File file1 = createFile("createAndReadPropertyFile-1", prop1); - - // read in properties, and compare - logger.info("Read in properties from new file"); - Properties prop2 = PropertyUtil.getProperties(file1); - - // they should match - assertEquals(prop1, prop2); - } - - /** - * This tests the 'PropertyUtil.Listener' interface. - */ - @Test - public void testListenerInterface() throws Exception - { - logger.info("testListenerInterface: test receipt of dynamic updates"); - - // create initial property file - Properties prop1 = new Properties(); - prop1.setProperty("p1", "p1 value"); - prop1.setProperty("p2", "p2 value"); - prop1.setProperty("p3", "p3 value"); - logger.info("Create initial properties file: " + prop1); - File file1 = createFile("createAndReadPropertyFile-2", prop1); - - // create a listener for the notification interface - Object[] returns = new Object[2]; - PropertyUtil.Listener listener = createListenerThread(returns); - - // read it in, and do a comparison - Properties prop2 = PropertyUtil.getProperties(file1, listener); - logger.info("Read in properties: " + prop2); - assertEquals(prop1, prop2); - assertEquals(prop2.getProperty("p1"), "p1 value"); - assertEquals(prop2.getProperty("p2"), "p2 value"); - assertEquals(prop2.getProperty("p3"), "p3 value"); - - // make some changes, and update the file (p3 is left unchanged) - prop2.remove("p1"); // remove one property - prop2.setProperty("p2", "new p2 value"); // change one property - prop2.setProperty("p4", "p4 value"); // add a new property - logger.info("Modified properties: " + prop2); - - // now, update the file, and wait for notification - synchronized(returns) - { - createFile("createAndReadPropertyFile-2", prop2); - - // wait up to 60 seconds, although we should receive notification - // in 10 seconds or less (if things are working) - returns.wait(60000L); - } - - // verify we have the updates - assertEquals(prop2, returns[0]); - - // verify that we have the expected set of keys - assertEquals(new TreeSet<String>(Arrays.asList(new String[]{"p1", "p2", "p4"})), - returns[1]); - } +public class PropertyUtilTest { + private static final Logger logger = LoggerFactory.getLogger(PropertyUtilTest.class); + + private static File directory = null; + + /** + * Test Setup -- Create a directory for temporary files. + */ + @BeforeClass + public static void setup() { + logger.info("setup: creating a temporary directory"); + + // create a directory for temporary files + directory = new File(UUID.randomUUID().toString()); + directory.mkdir(); + } + + /** + * Test Cleanup -- Remove temporary files. + */ + @AfterClass + public static void teardown() { + logger.info("teardown: remove the temporary directory"); + + // the assumption is that we only have one level of temporary files + for (File file : directory.listFiles()) { + file.delete(); + } + directory.delete(); + } + + /** + * Utility method to write a properties file. + * + * @param name the file name, relative to the temporary directory + * @param the properties to store in the file + * @return a File instance associated with the newly-created file + * @throws IOException if the file can't be created for some reason + */ + File createFile(String name, Properties properties) throws IOException { + File file = new File(directory, name); + try (FileOutputStream fos = new FileOutputStream(file)) { + properties.store(fos, "Property file '" + name + "'"); + } + return (file); + } + + /** + * Create a 'PropertyUtil.Listener' subclass, which receives property + * file updates. It stores the latest values in an array, and notifies + * any thread waiting on this array. + * + * @param returns this is an array of length 2 -- the first entry will + * contain the 'properties' value, and the second will contain + * 'changedKeys'. It is also used to signal any waiting thread + * using 'returns.notifyAll()'. + */ + PropertyUtil.Listener createListenerThread(final Object[] returns) { + return (new PropertyUtil.Listener() { + public void propertiesChanged(Properties properties, Set<String> changedKeys) { + // When a notification is received, store the values in the + // 'returns' array, and signal using the same array. + logger.info("Listener invoked: properties=" + properties + + ", changedKeys=" + changedKeys); + returns[0] = properties; + returns[1] = changedKeys; + synchronized (returns) { + returns.notifyAll(); + } + } + }); + } + + /** + * Test the basic properties file interface. + */ + @Test + public void testGetProperties() throws Exception { + logger.info("testGetProperties: test the basic properties file interface"); + + // copy system properties + logger.info("Copy system properties to a file"); + Properties prop1 = System.getProperties(); + File file1 = createFile("createAndReadPropertyFile-1", prop1); + + // read in properties, and compare + logger.info("Read in properties from new file"); + Properties prop2 = PropertyUtil.getProperties(file1); + + // they should match + assertEquals(prop1, prop2); + } + + /** + * This tests the 'PropertyUtil.Listener' interface. + */ + @Test + public void testListenerInterface() throws Exception { + logger.info("testListenerInterface: test receipt of dynamic updates"); + + // create initial property file + Properties prop1 = new Properties(); + prop1.setProperty("p1", "p1 value"); + prop1.setProperty("p2", "p2 value"); + prop1.setProperty("p3", "p3 value"); + logger.info("Create initial properties file: " + prop1); + File file1 = createFile("createAndReadPropertyFile-2", prop1); + + // create a listener for the notification interface + Object[] returns = new Object[2]; + PropertyUtil.Listener listener = createListenerThread(returns); + + // read it in, and do a comparison + Properties prop2 = PropertyUtil.getProperties(file1, listener); + logger.info("Read in properties: " + prop2); + assertEquals(prop1, prop2); + assertEquals("p1 value", prop2.getProperty("p1")); + assertEquals("p2 value", prop2.getProperty("p2")); + assertEquals("p3 value", prop2.getProperty("p3")); + + // make some changes, and update the file (p3 is left unchanged) + prop2.remove("p1"); // remove one property + prop2.setProperty("p2", "new p2 value"); // change one property + prop2.setProperty("p4", "p4 value"); // add a new property + logger.info("Modified properties: " + prop2); + + // now, update the file, and wait for notification + synchronized (returns) { + createFile("createAndReadPropertyFile-2", prop2); + + // wait up to 60 seconds, although we should receive notification + // in 10 seconds or less (if things are working) + returns.wait(60000L); + } + + // verify we have the updates + assertEquals(prop2, returns[0]); + + // verify that we have the expected set of keys + assertEquals(new TreeSet<String>(Arrays.asList(new String[]{"p1", "p2", "p4"})), + returns[1]); + } } diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/ReferenceTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/ReferenceTest.java index 1d6b111a..255c7f13 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/ReferenceTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/ReferenceTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; + import org.junit.Test; import org.onap.policy.drools.utils.Reference; @@ -54,22 +55,22 @@ public class ReferenceTest { public void testCompareAndSet() { Reference<Integer> val = new Reference<>(null); - Integer v = 100; + Integer valCompare = 100; // try an incorrect value - should fail and leave value unchanged - assertFalse(val.compareAndSet(500, v)); + assertFalse(val.compareAndSet(500, valCompare)); assertNull(val.get()); - assertTrue(val.compareAndSet(null, v)); - assertEquals(v, val.get()); + assertTrue(val.compareAndSet(null, valCompare)); + assertEquals(valCompare, val.get()); // try an incorrect value - should fail and leave value unchanged Integer v2 = 200; assertFalse(val.compareAndSet(600, v2)); - assertEquals(v, val.get()); + assertEquals(valCompare, val.get()); // now try again, this time with the correct value - assertTrue(val.compareAndSet(v, v2)); + assertTrue(val.compareAndSet(valCompare, v2)); assertEquals(v2, val.get()); Integer v3 = 300; diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/ReflectionUtilTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/ReflectionUtilTest.java index 0cb51060..706c5f24 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/ReflectionUtilTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/ReflectionUtilTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-utils * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.policy.drools.utils; import static org.junit.Assert.assertEquals; @@ -62,23 +63,23 @@ public class ReflectionUtilTest { @Test(expected = IllegalArgumentException.class) public void testException1() { - ReflectionUtil.fetchClass(null, "org.onap.policy.drools.utils.ReflectionUtil"); + ReflectionUtil.fetchClass(null, "org.onap.policy.drools.utils.ReflectionUtil"); } @Test(expected = IllegalArgumentException.class) public void testException2() { Class<?> class1; - try { - class1 = Class.forName("org.onap.policy.drools.utils.ReflectionUtil"); - ClassLoader classLoader = class1.getClassLoader(); - ReflectionUtil.fetchClass(classLoader, null); - } catch (ClassNotFoundException e) { - fail(); - } + try { + class1 = Class.forName("org.onap.policy.drools.utils.ReflectionUtil"); + ClassLoader classLoader = class1.getClassLoader(); + ReflectionUtil.fetchClass(classLoader, null); + } catch (ClassNotFoundException e) { + fail(); + } } @Test public void testException3() throws ClassNotFoundException { - assertNull(ReflectionUtil.fetchClass(ClassLoader.getSystemClassLoader(), "foo.bar")); + assertNull(ReflectionUtil.fetchClass(ClassLoader.getSystemClassLoader(), "foo.bar")); } } diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/LoggerUtilTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/LoggerUtilTest.java index d773b265..be1a8a97 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/LoggerUtilTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/LoggerUtilTest.java @@ -17,9 +17,11 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.policy.drools.utils.logging; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import org.junit.Test; import org.slf4j.Logger; @@ -27,30 +29,30 @@ import org.slf4j.LoggerFactory; public class LoggerUtilTest { - @Test - public void test() { + @Test + public void test() { - Logger logger = LoggerFactory.getLogger(LoggerUtilTest.class); + Logger logger = LoggerFactory.getLogger(LoggerUtilTest.class); - assertTrue(logger.isInfoEnabled()); + assertTrue(logger.isInfoEnabled()); - logger.info("line 1"); - logger.info(LoggerUtil.METRIC_LOG_MARKER, "line 1 Metric"); - logger.info(LoggerUtil.TRANSACTION_LOG_MARKER, "line 1 Transaction"); + logger.info("line 1"); + logger.info(LoggerUtil.METRIC_LOG_MARKER, "line 1 Metric"); + logger.info(LoggerUtil.TRANSACTION_LOG_MARKER, "line 1 Transaction"); - LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "warn"); - logger.info("line 2"); - logger.info(LoggerUtil.METRIC_LOG_MARKER, "line 2 Metric"); - logger.info(LoggerUtil.TRANSACTION_LOG_MARKER, "line 2 Transaction"); + LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "warn"); + logger.info("line 2"); + logger.info(LoggerUtil.METRIC_LOG_MARKER, "line 2 Metric"); + logger.info(LoggerUtil.TRANSACTION_LOG_MARKER, "line 2 Transaction"); - assertFalse(logger.isInfoEnabled()); + assertFalse(logger.isInfoEnabled()); - LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "debug"); - logger.debug("line 3"); - logger.debug(LoggerUtil.METRIC_LOG_MARKER, "line 3 Metric"); - logger.debug(LoggerUtil.TRANSACTION_LOG_MARKER, "line 3 Transaction"); + LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "debug"); + logger.debug("line 3"); + logger.debug(LoggerUtil.METRIC_LOG_MARKER, "line 3 Metric"); + logger.debug(LoggerUtil.TRANSACTION_LOG_MARKER, "line 3 Transaction"); - assertTrue(logger.isDebugEnabled()); - } + assertTrue(logger.isDebugEnabled()); + } } diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/MDCTransactionTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/MdcTransactionTest.java index f6c48daf..1b7a3c7d 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/MDCTransactionTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/MdcTransactionTest.java @@ -16,16 +16,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.onap.policy.drools.utils.logging; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import java.time.Duration; import java.time.Instant; import org.junit.Test; import org.slf4j.MDC; -public class MDCTransactionTest { +public class MdcTransactionTest { @Test public void resetSubTransaction() { @@ -114,31 +118,31 @@ public class MDCTransactionTest { @Test public void flush() { MDCTransaction trans = - MDCTransaction.newTransaction(). - setRequestId(null). - setInvocationId(null). - setPartner(null). - setVirtualServerName(null). - setServer(null). - setServerIpAddress(null). - setServerFqdn(null). - setServiceName(null). - setStartTime(null). - setEndTime(null). - setServiceInstanceId("service-instance-id"). - setInstanceUUID(null). - setProcessKey("process-key"). - setStatusCode("status-code"). - setResponseCode("response-code"). - setResponseDescription("response-description"). - setSeverity("severity"). - setAlertSeverity("alert-severity"). - setTargetEntity("target-entity"). - setTargetServiceName("target-service-name"). - setTargetVirtualEntity("target-virtual-entity"). - setClientIpAddress("client-ip-address"). - setRemoteHost("remote-host"). - flush(); + MDCTransaction.newTransaction() + .setRequestId(null) + .setInvocationId(null) + .setPartner(null) + .setVirtualServerName(null) + .setServer(null) + .setServerIpAddress(null) + .setServerFqdn(null) + .setServiceName(null) + .setStartTime(null) + .setEndTime(null) + .setServiceInstanceId("service-instance-id") + .setInstanceUUID(null) + .setProcessKey("process-key") + .setStatusCode("status-code") + .setResponseCode("response-code") + .setResponseDescription("response-description") + .setSeverity("severity") + .setAlertSeverity("alert-severity") + .setTargetEntity("target-entity") + .setTargetServiceName("target-service-name") + .setTargetVirtualEntity("target-virtual-entity") + .setClientIpAddress("client-ip-address") + .setRemoteHost("remote-host") + .flush(); assertTransactionFields(trans); @@ -180,18 +184,18 @@ public class MDCTransactionTest { assertEquals(trans.getClientIpAddress(), MDC.get(MDCTransaction.CLIENT_IP_ADDRESS)); assertEquals(trans.getRemoteHost(), MDC.get(MDCTransaction.REMOTE_HOST)); - assertEquals(trans.getServiceInstanceId(),"service-instance-id"); - assertEquals(trans.getProcessKey(),"process-key"); - assertEquals(trans.getStatusCode(),"status-code"); - assertEquals(trans.getResponseCode(),"response-code"); - assertEquals(trans.getResponseDescription(),"response-description"); - assertEquals(trans.getSeverity(),"severity"); - assertEquals(trans.getAlertSeverity(),"alert-severity"); - assertEquals(trans.getTargetEntity(),"target-entity"); - assertEquals(trans.getTargetServiceName(),"target-service-name"); - assertEquals(trans.getTargetVirtualEntity(),"target-virtual-entity"); - assertEquals(trans.getClientIpAddress(),"client-ip-address"); - assertEquals(trans.getRemoteHost(),"remote-host"); + assertEquals("service-instance-id", trans.getServiceInstanceId()); + assertEquals("process-key", trans.getProcessKey()); + assertEquals("status-code", trans.getStatusCode()); + assertEquals("response-code", trans.getResponseCode()); + assertEquals("response-description", trans.getResponseDescription()); + assertEquals("severity", trans.getSeverity()); + assertEquals("alert-severity", trans.getAlertSeverity()); + assertEquals("target-entity", trans.getTargetEntity()); + assertEquals("target-service-name", trans.getTargetServiceName()); + assertEquals("target-virtual-entity", trans.getTargetVirtualEntity()); + assertEquals("client-ip-address", trans.getClientIpAddress()); + assertEquals("remote-host", trans.getRemoteHost()); } @Test @@ -235,20 +239,20 @@ public class MDCTransactionTest { assertNotNull(subTrans.getStartTime()); assertNullSubTransactionFieldsButInvocationId(trans); - subTrans.setServiceInstanceId("service-instance-id"). - setInstanceUUID(null). - setProcessKey("process-key"). - setStatusCode("status-code"). - setResponseCode("response-code"). - setResponseDescription("response-description"). - setSeverity("severity"). - setAlertSeverity("alert-severity"). - setTargetEntity("target-entity"). - setTargetServiceName("target-service-name"). - setTargetVirtualEntity("target-virtual-entity"). - setClientIpAddress("client-ip-address"). - setRemoteHost("remote-host"). - setEndTime(Instant.now()); + subTrans.setServiceInstanceId("service-instance-id") + .setInstanceUUID(null) + .setProcessKey("process-key") + .setStatusCode("status-code") + .setResponseCode("response-code") + .setResponseDescription("response-description") + .setSeverity("severity") + .setAlertSeverity("alert-severity") + .setTargetEntity("target-entity") + .setTargetServiceName("target-service-name") + .setTargetVirtualEntity("target-virtual-entity") + .setClientIpAddress("client-ip-address") + .setRemoteHost("remote-host") + .setEndTime(Instant.now()); subTrans.setStatusCode(false).setResponseCode("400"); |