From 6abeb297254942c48722c2da0e7c355d523fe307 Mon Sep 17 00:00:00 2001 From: Guo Ruijing Date: Fri, 28 Jul 2017 08:23:01 +0000 Subject: [POLICY-72] replace openecomp for drools-pdp Change-Id: I8aa8e32d3ba10f7c655b50e97aaf6865514d4777 Signed-off-by: Guo Ruijing --- .../onap/policy/drools/utils/OrderedService.java | 41 +++ .../policy/drools/utils/OrderedServiceImpl.java | 156 +++++++++ .../java/org/onap/policy/drools/utils/Pair.java | 51 +++ .../org/onap/policy/drools/utils/PropertyUtil.java | 385 +++++++++++++++++++++ .../onap/policy/drools/utils/ReflectionUtil.java | 88 +++++ .../java/org/onap/policy/drools/utils/Triple.java | 45 +++ .../policy/drools/utils/OrderedService.java | 41 --- .../policy/drools/utils/OrderedServiceImpl.java | 156 --------- .../org/openecomp/policy/drools/utils/Pair.java | 51 --- .../policy/drools/utils/PropertyUtil.java | 385 --------------------- .../policy/drools/utils/ReflectionUtil.java | 88 ----- .../org/openecomp/policy/drools/utils/Triple.java | 45 --- 12 files changed, 766 insertions(+), 766 deletions(-) create mode 100644 policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedService.java create mode 100644 policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedServiceImpl.java create mode 100644 policy-utils/src/main/java/org/onap/policy/drools/utils/Pair.java create mode 100644 policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java create mode 100644 policy-utils/src/main/java/org/onap/policy/drools/utils/ReflectionUtil.java create mode 100644 policy-utils/src/main/java/org/onap/policy/drools/utils/Triple.java delete mode 100644 policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedService.java delete mode 100644 policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedServiceImpl.java delete mode 100644 policy-utils/src/main/java/org/openecomp/policy/drools/utils/Pair.java delete mode 100644 policy-utils/src/main/java/org/openecomp/policy/drools/utils/PropertyUtil.java delete mode 100644 policy-utils/src/main/java/org/openecomp/policy/drools/utils/ReflectionUtil.java delete mode 100644 policy-utils/src/main/java/org/openecomp/policy/drools/utils/Triple.java (limited to 'policy-utils/src/main/java/org') 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 new file mode 100644 index 00000000..75a3cd7d --- /dev/null +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedService.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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 file 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.utils; + +/** + * This is a base interface that is used to control the order of a list + * of services (features) discovered via 'ServiceLoader'. See + * 'OrderedServiceImpl' for more details. + */ +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();} +} 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 new file mode 100644 index 00000000..88a53313 --- /dev/null +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/OrderedServiceImpl.java @@ -0,0 +1,156 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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 file 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.utils; + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.ServiceLoader; + +import org.slf4j.Logger; +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 +{ + // logger + private static Logger logger = LoggerFactory.getLogger(OrderedServiceImpl.class); + + // sorted list of instances implementing the service + private List implementers = null; + + // 'ServiceLoader' that is used to discover and create the services + private ServiceLoader serviceLoader = null; //ServiceLoader.load(T.class); + + /** + * 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 clazz) + { + // This constructor wouldn't be needed if 'T.class' was legal + serviceLoader = ServiceLoader.load(clazz); + } + + /** + * @return the sorted list of services implementing interface 'T' discovered + * by 'ServiceLoader'. + */ + public synchronized List getList() + { + if (implementers == null) + { + rebuildList(); + } + return(implementers); + } + + /** + * 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 rebuildList() + { + // build a list of all of the current implementors + List tmp = new LinkedList(); + for (T service : serviceLoader) + { + tmp.add((T)getSingleton(service)); + } + + // Sort the list according to sequence number, and then alphabetically + // according to full class name. + Collections.sort(tmp, new Comparator() + { + public int compare(T o1, T o2) + { + int s1 = o1.getSequenceNumber(); + int s2 = o2.getSequenceNumber(); + int rval; + if (s1 < s2) + { + rval = -1; + } + else if (s1 > s2) + { + rval = 1; + } + else + { + rval = o1.getClass().getName().compareTo + (o2.getClass().getName()); + } + return(rval); + } + }); + + // create an unmodifiable version of this list + implementers = Collections.unmodifiableList(tmp); + logger.info("***** OrderedServiceImpl implementers:\n {}", implementers); + return(implementers); + } + + // use this to ensure that we only use one unique instance of each class + @SuppressWarnings("rawtypes") + static private HashMap classToSingleton = + new HashMap<>(); + + /** + * 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. + */ + static private 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 new file mode 100644 index 00000000..ee0bb6f6 --- /dev/null +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/Pair.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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 file 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.utils; + +public class Pair { + + protected F first; + protected 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(); + } +} 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 new file mode 100644 index 00000000..9cfe2ed1 --- /dev/null +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/PropertyUtil.java @@ -0,0 +1,385 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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 file 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Properties; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; + +/** + * This class provides utilities to read properties from a properties + * file, and optionally get notifications of future changes + */ +public class PropertyUtil +{ + /** + * 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. + */ + static public 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. + */ + static public Properties getProperties(String fileName) throws IOException + { + return(getProperties(new File(fileName))); + } + + /* ============================================================ */ + + // timer thread used for polling for property file changes + private static Timer timer = null; + + /** + * This is the callback interface, used for sending notifications of + * changes in the properties file. + */ + 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 changedKeys); + } + + // this table maps canonical file into a 'ListenerRegistration' instance + static private HashMap registrations = + new HashMap(); + + /** + * 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 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); + + if (timer == null) + { + // 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() + { + public void run() + { + try + { + poll(); + } + catch (Exception e) + { + System.err.println(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.size() == 0) + { + 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 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 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.size() != 0) + { + // 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 tmpChangedProperties = + new HashSet(changedProperties); + + // Do the notification in a separate thread, so blocking + // won't cause any problems. + new Thread() + { + 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. + */ + static public Properties getProperties(File file, Listener listener) + throws IOException + { + if (listener == null) + { + // no listener specified -- just fetch the properties + return(getProperties(file)); + } + + // Convert the file to a canonical form in order to avoid the situation + // where different names refer to the same file. + file = file.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(file); + if (reg == null) + { + // a new registration is needed + reg = new ListenerRegistration(file); + } + 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. + */ + static public 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 + */ + static public 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 + */ + static public void stopListening(String fileName, Listener listener) + { + stopListening(new File(fileName), listener); + } + +} 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 new file mode 100644 index 00000000..eeb7f1f6 --- /dev/null +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/ReflectionUtil.java @@ -0,0 +1,88 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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 file 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. + * ============LICENSE_END========================================================= + */ + +/** + * + */ +package org.onap.policy.drools.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +/** + * Reflection utilities + * + */ +public class ReflectionUtil { + + protected final static Logger logger = LoggerFactory.getLogger(ReflectionUtil.class); + + /** + * 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) + throws IllegalArgumentException { + 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 { + Class aClass = Class.forName(className, + true, + classLoader); + return aClass; + } catch (Exception e) { + logger.error("FETCHED-CLASS {} IN {} does NOT EXIST", className, classLoader); + } + + 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) + throws IllegalArgumentException { + 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)); + } + +} 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 new file mode 100644 index 00000000..530d57a5 --- /dev/null +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/Triple.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * policy-utils + * ================================================================================ + * 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 file 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.utils; + +public class Triple { + + private F first; + private S second; + private T third; + + public Triple(F first, S second, T third){ + this.first = first; + this.second = second; + this.third = third; + } + public F first(){ return this.first; } + + public S second(){ return this.second; } + + public T third(){ return this.third; } + + public void first(F first){ this.first = first; } + + public void second(S second){ this.second = second; } + + public void third(T third){ this.third = third; } +} diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedService.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedService.java deleted file mode 100644 index 0851413c..00000000 --- a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedService.java +++ /dev/null @@ -1,41 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-utils - * ================================================================================ - * 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 file 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.utils; - -/** - * This is a base interface that is used to control the order of a list - * of services (features) discovered via 'ServiceLoader'. See - * 'OrderedServiceImpl' for more details. - */ -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();} -} diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedServiceImpl.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedServiceImpl.java deleted file mode 100644 index 72bf7b8b..00000000 --- a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/OrderedServiceImpl.java +++ /dev/null @@ -1,156 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-utils - * ================================================================================ - * 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 file 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.utils; - -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.ServiceLoader; - -import org.slf4j.Logger; -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 -{ - // logger - private static Logger logger = LoggerFactory.getLogger(OrderedServiceImpl.class); - - // sorted list of instances implementing the service - private List implementers = null; - - // 'ServiceLoader' that is used to discover and create the services - private ServiceLoader serviceLoader = null; //ServiceLoader.load(T.class); - - /** - * 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 clazz) - { - // This constructor wouldn't be needed if 'T.class' was legal - serviceLoader = ServiceLoader.load(clazz); - } - - /** - * @return the sorted list of services implementing interface 'T' discovered - * by 'ServiceLoader'. - */ - public synchronized List getList() - { - if (implementers == null) - { - rebuildList(); - } - return(implementers); - } - - /** - * 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 rebuildList() - { - // build a list of all of the current implementors - List tmp = new LinkedList(); - for (T service : serviceLoader) - { - tmp.add((T)getSingleton(service)); - } - - // Sort the list according to sequence number, and then alphabetically - // according to full class name. - Collections.sort(tmp, new Comparator() - { - public int compare(T o1, T o2) - { - int s1 = o1.getSequenceNumber(); - int s2 = o2.getSequenceNumber(); - int rval; - if (s1 < s2) - { - rval = -1; - } - else if (s1 > s2) - { - rval = 1; - } - else - { - rval = o1.getClass().getName().compareTo - (o2.getClass().getName()); - } - return(rval); - } - }); - - // create an unmodifiable version of this list - implementers = Collections.unmodifiableList(tmp); - logger.info("***** OrderedServiceImpl implementers:\n {}", implementers); - return(implementers); - } - - // use this to ensure that we only use one unique instance of each class - @SuppressWarnings("rawtypes") - static private HashMap classToSingleton = - new HashMap<>(); - - /** - * 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. - */ - static private 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/openecomp/policy/drools/utils/Pair.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Pair.java deleted file mode 100644 index a5e34695..00000000 --- a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Pair.java +++ /dev/null @@ -1,51 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-utils - * ================================================================================ - * 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 file 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.utils; - -public class Pair { - - protected F first; - protected 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(); - } -} diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/PropertyUtil.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/PropertyUtil.java deleted file mode 100644 index 1e8dc267..00000000 --- a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/PropertyUtil.java +++ /dev/null @@ -1,385 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-utils - * ================================================================================ - * 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 file 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.utils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Properties; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; - -/** - * This class provides utilities to read properties from a properties - * file, and optionally get notifications of future changes - */ -public class PropertyUtil -{ - /** - * 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. - */ - static public 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. - */ - static public Properties getProperties(String fileName) throws IOException - { - return(getProperties(new File(fileName))); - } - - /* ============================================================ */ - - // timer thread used for polling for property file changes - private static Timer timer = null; - - /** - * This is the callback interface, used for sending notifications of - * changes in the properties file. - */ - 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 changedKeys); - } - - // this table maps canonical file into a 'ListenerRegistration' instance - static private HashMap registrations = - new HashMap(); - - /** - * 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 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); - - if (timer == null) - { - // 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() - { - public void run() - { - try - { - poll(); - } - catch (Exception e) - { - System.err.println(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.size() == 0) - { - 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 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 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.size() != 0) - { - // 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 tmpChangedProperties = - new HashSet(changedProperties); - - // Do the notification in a separate thread, so blocking - // won't cause any problems. - new Thread() - { - 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. - */ - static public Properties getProperties(File file, Listener listener) - throws IOException - { - if (listener == null) - { - // no listener specified -- just fetch the properties - return(getProperties(file)); - } - - // Convert the file to a canonical form in order to avoid the situation - // where different names refer to the same file. - file = file.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(file); - if (reg == null) - { - // a new registration is needed - reg = new ListenerRegistration(file); - } - 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. - */ - static public 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 - */ - static public 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 - */ - static public void stopListening(String fileName, Listener listener) - { - stopListening(new File(fileName), listener); - } - -} diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/ReflectionUtil.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/ReflectionUtil.java deleted file mode 100644 index 0d82e847..00000000 --- a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/ReflectionUtil.java +++ /dev/null @@ -1,88 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-utils - * ================================================================================ - * 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 file 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. - * ============LICENSE_END========================================================= - */ - -/** - * - */ -package org.openecomp.policy.drools.utils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -/** - * Reflection utilities - * - */ -public class ReflectionUtil { - - protected final static Logger logger = LoggerFactory.getLogger(ReflectionUtil.class); - - /** - * 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) - throws IllegalArgumentException { - 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 { - Class aClass = Class.forName(className, - true, - classLoader); - return aClass; - } catch (Exception e) { - logger.error("FETCHED-CLASS {} IN {} does NOT EXIST", className, classLoader); - } - - 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) - throws IllegalArgumentException { - 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)); - } - -} diff --git a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Triple.java b/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Triple.java deleted file mode 100644 index 214d949e..00000000 --- a/policy-utils/src/main/java/org/openecomp/policy/drools/utils/Triple.java +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-utils - * ================================================================================ - * 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 file 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. - * ============LICENSE_END========================================================= - */ - -package org.openecomp.policy.drools.utils; - -public class Triple { - - private F first; - private S second; - private T third; - - public Triple(F first, S second, T third){ - this.first = first; - this.second = second; - this.third = third; - } - public F first(){ return this.first; } - - public S second(){ return this.second; } - - public T third(){ return this.third; } - - public void first(F first){ this.first = first; } - - public void second(S second){ this.second = second; } - - public void third(T third){ this.third = third; } -} -- cgit 1.2.3-korg