summaryrefslogtreecommitdiffstats
path: root/core/utils/provider
diff options
context:
space:
mode:
Diffstat (limited to 'core/utils/provider')
-rw-r--r--core/utils/provider/pom.xml20
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/StructuredPropertyHelper.java257
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/configuration/ConfigurationFactory.java5
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Allocator.java45
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/CacheManagement.java33
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/CachedElement.java217
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Destructor.java44
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Pool.java368
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolDrainedException.java48
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolException.java89
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolExtensionException.java46
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolSpecificationException.java47
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/logging/LoggingConstantsTest.java59
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/logging/LoggingUtilsTest.java357
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/CachedElementTest.java285
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/Element.java77
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolDrainedExceptionTest.java35
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolExceptionTest.java72
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolExtensionExceptionTest.java35
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolTest.java335
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/Testable.java34
21 files changed, 2505 insertions, 3 deletions
diff --git a/core/utils/provider/pom.xml b/core/utils/provider/pom.xml
index 476448775..bd85ff3a1 100644
--- a/core/utils/provider/pom.xml
+++ b/core/utils/provider/pom.xml
@@ -59,6 +59,26 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/StructuredPropertyHelper.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/StructuredPropertyHelper.java
new file mode 100644
index 000000000..c9fc56c34
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/StructuredPropertyHelper.java
@@ -0,0 +1,257 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This class is used to assemble properties that are defined using a structured name into groups, and allow them to be
+ * processed as sets of definitions.
+ * <p>
+ * For example, a structured name uses a dotted-notation, like "provider.name". Further, the nodes of the structured
+ * name may be serialized using a suffix ordinal number (e.g., "provider1.name"). These structured properties form a
+ * hierarchical name space where the names are grouped together and can be retrieved as a set.
+ * </p>
+ *
+ */
+
+public class StructuredPropertyHelper {
+
+ /**
+ * This method scans the properties object for all properties that match the root name and constructs a list of
+ * structured property node graphs that represents the namespaces of the properties.
+ * <p>
+ * For example, assume that there are structured properties of the form "provider1.name", "provider2.name",
+ * "provider3.name", and so forth. There may also be other subordinate properties as well (e.g., "provider1.type").
+ * This method would construct a list of graphs of nodes, where each node represents one value of the structured
+ * name. The roots would be the values "provider1", "provider2", "provider3", and so forth. The values of the
+ * subordinate nodes would be the second, third, and so forth name nodes of the compound name. The value of the
+ * property is associated with nodes that are representative of the leaf of the name space.
+ * </p>
+ *
+ * @param properties
+ * The properties to be processed
+ * @param prefix
+ * The prefix of the root structured property name
+ * @return The node graph of the properties
+ */
+ public static List<Node> getStructuredProperties(Properties properties, String prefix) {
+ List<Node> roots = new ArrayList<>();
+
+ for (String name : properties.stringPropertyNames()) {
+ if (name.startsWith(prefix)) {
+ String value = properties.getProperty(name);
+ processNamespace(roots, name, value);
+ }
+ }
+
+ return roots;
+ }
+
+ /**
+ * This method recursively walks the name space of the structured property and constructs the node graph to
+ * represent the property
+ *
+ * @param nodes
+ * The collection of nodes for the current level of the name space
+ * @param propertyName
+ * The name of the node
+ * @param value
+ * The value, if any
+ * @return The node for this level in the namespace
+ */
+ @SuppressWarnings("nls")
+ private static Node processNamespace(List<Node> nodes, String propertyName, String value) {
+ String[] tokens = propertyName.split("\\.", 2);
+ String nodeName = normalizeNodeName(tokens[0]);
+
+ Node namespaceNode = null;
+ for (Node node : nodes) {
+ if (node.getName().equals(nodeName)) {
+ namespaceNode = node;
+ break;
+ }
+ }
+ if (namespaceNode == null) {
+ namespaceNode = new Node();
+ namespaceNode.setName(nodeName);
+ nodes.add(namespaceNode);
+ }
+
+ if (tokens.length == 1 || tokens[1] == null || tokens[1].length() == 0) {
+ namespaceNode.setValue(value);
+ } else {
+ processNamespace(namespaceNode.getChildren(), tokens[1], value);
+ }
+
+ return namespaceNode;
+ }
+
+ /**
+ * This method normalizes a node name of the structured property name by removing leading and trailing whitespace,
+ * and by converting any ordinal position to a simple expression without leading zeroes.
+ *
+ * @param token
+ * The token to be normalized
+ * @return The normalized name, or null if the token was null;
+ */
+ @SuppressWarnings("nls")
+ private static String normalizeNodeName(String token) {
+ if (token == null) {
+ return null;
+ }
+
+ StringBuilder builder = new StringBuilder(token.trim());
+ Pattern pattern = Pattern.compile("([^0-9]+)([0-9]*)");
+ Matcher matcher = pattern.matcher(builder);
+ if (matcher.matches()) {
+ String nameRoot = matcher.group(1);
+ String ordinal = matcher.group(2);
+ if (ordinal != null && ordinal.length() > 0) {
+ int i = Integer.parseInt(ordinal);
+ builder.setLength(0);
+ builder.append(nameRoot);
+ builder.append(Integer.toString(i));
+ }
+ }
+ return builder.toString();
+ }
+
+ /**
+ * This class represents a node in the structured property name space
+ *
+ */
+ public static class Node implements Comparable<Node> {
+
+ /**
+ * The name of the structured property node
+ */
+ private String name;
+
+ /**
+ * If the node is a leaf, then the value of the property
+ */
+ private String value;
+
+ /**
+ * If the node is not a leaf, then the sub-nodes of the property
+ */
+ private List<Node> children;
+
+ /**
+ * @return the value of name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name
+ * the value for name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the value of value
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * @param value
+ * the value for value
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ /**
+ * @return the value of children
+ */
+ public List<Node> getChildren() {
+ if (children == null) {
+ children = new ArrayList<>();
+ }
+ return children;
+ }
+
+ /**
+ * @see Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return name.hashCode() + (value != null ? value.hashCode() : children.hashCode());
+ }
+
+ /**
+ * @see Object#equals(Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null)
+ return false;
+ if (this.getClass() != obj.getClass())
+ return false;
+
+ Node other = (Node) obj;
+ boolean result = name.equals(other.name);
+
+ if (value == null) {
+ result &= other.value == null;
+ } else {
+ result &= value.equals(other.value);
+ }
+ if (children == null) {
+ result &= other.children == null;
+ } else {
+ result &= children.equals(other.children);
+ }
+ return result;
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ @SuppressWarnings("nls")
+ @Override
+ public String toString() {
+ if (value != null) {
+ return String.format("%s = %s", name, value);
+ }
+ return String.format("%s.%s", name, children.toString());
+ }
+
+ @Override
+ public int compareTo(Node o) {
+ return name.compareTo(o.name);
+ }
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/configuration/ConfigurationFactory.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/configuration/ConfigurationFactory.java
index 05c132d0f..9f0289458 100644
--- a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/configuration/ConfigurationFactory.java
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/configuration/ConfigurationFactory.java
@@ -124,7 +124,7 @@ public final class ConfigurationFactory {
/**
* The default properties resource to be loaded
*/
- private static final String DEFAULT_PROPERTIES = "org/onap/appc/default.properties";
+ private static final String DEFAULT_PROPERTIES = "default.properties";
/**
* This collection allows for special configurations to be created and maintained, organized by
@@ -301,8 +301,7 @@ public final class ConfigurationFactory {
/*
* Load the defaults (if any are present)
*/
- InputStream in = Thread.currentThread().getContextClassLoader()
- .getResourceAsStream(DEFAULT_PROPERTIES);
+ InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(DEFAULT_PROPERTIES);
if (in != null) {
logger.info(Msg.LOADING_DEFAULTS, DEFAULT_PROPERTIES);
try {
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Allocator.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Allocator.java
new file mode 100644
index 000000000..a9c781f65
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Allocator.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+import java.io.Closeable;
+
+/**
+ * This interface is used to supply an object that will be called by the pool manager whenever a new widget must be
+ * allocated.
+ * @param <T>
+ * The generic type that we are caching.
+ */
+
+public interface Allocator<T extends Closeable> {
+
+ /**
+ * Allocate an object of type <T> and return it to the pool
+ *
+ * @param pool
+ * The pool that the object is to be allocated to
+ * @return An object of type T
+ */
+ T allocate(org.onap.ccsdk.sli.core.utils.pool.Pool<T> pool);
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/CacheManagement.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/CacheManagement.java
new file mode 100644
index 000000000..d3d47e759
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/CacheManagement.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+public interface CacheManagement {
+
+ /**
+ * @return The object that is actually being wrapped and cached
+ */
+ Object getWrappedObject();
+
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/CachedElement.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/CachedElement.java
new file mode 100644
index 000000000..2816edd20
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/CachedElement.java
@@ -0,0 +1,217 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Modifications Copyright (C) 2019 IBM
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * This class is used as a "wrapper" for any closeable elements that are cached in a pool. It is
+ * implemented as a dynamic proxy, so that it appears to be the same class of object to the client
+ * as the interface being cached. The generic type being cached MUST be an interface.
+ *
+ * @param <T> The generic type that we create a cached element for. This type is used to wrap
+ * instances of this type and expose access to the {@link Closeable} interface by
+ * using a dynamic proxy.
+ */
+
+public class CachedElement<T extends Closeable>
+ implements Closeable, InvocationHandler, CacheManagement {
+ private static final EELFLogger LOG = EELFManager.getInstance().getLogger(CachedElement.class);
+
+ /**
+ * The pool that is managing this cached element
+ */
+ private Pool<T> pool;
+
+ /**
+ * The element that we are caching in the pool
+ */
+ private T element;
+
+ /**
+ * A thread-safe atomic indicator that tells us that the wrapped element has been released to
+ * the pool already, and not to do it again.
+ */
+ private AtomicBoolean released = new AtomicBoolean(false);
+
+ /**
+ * Create a new instance of a cached element dynamic proxy for use in the pool.
+ * <p>
+ * This returns an instance of the proxy to the caller that appears to be the same interface(s)
+ * as the object being cached. The dynamic proxy then intercepts all open and close semantics
+ * and directs that element to the pool.
+ * </p>
+ * <p>
+ * If the object being proxied does not implement the {@link CacheManagement} interface, then
+ * that interface is added to the dynamic proxy being created. This interface is actually
+ * implemented by the invocation handler (this object) for the proxy and allows direct access to
+ * the wrapped object inside the proxy.
+ * </p>
+ *
+ * @param pool The pool that we are caching these elements within
+ * @param element The element actually being cached
+ * @param interfaces The interface list of interfaces the element must implement (usually one)
+ * @return The dynamic proxy
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends Closeable> T newInstance(Pool<T> pool, T element,
+ Class<?>[] interfaces) {
+ ClassLoader cl = element.getClass().getClassLoader();
+ CachedElement<T> ce = new CachedElement<>(pool, element);
+ boolean found = false;
+ for (Class<?> intf : interfaces) {
+ if (intf.isAssignableFrom(CacheManagement.class)) {
+ found = true;
+ break;
+ }
+ }
+
+ int length = found ? interfaces.length : interfaces.length + 1;
+ Class<?>[] proxyInterfaces = new Class[length];
+ System.arraycopy(interfaces, 0, proxyInterfaces, 0, interfaces.length);
+
+ if (!found) {
+ proxyInterfaces[interfaces.length] = CacheManagement.class;
+ }
+
+ return (T) Proxy.newProxyInstance(cl, proxyInterfaces, ce);
+ }
+
+ /**
+ * Construct a cached element and assign it to the pool as a free element
+ *
+ * @param pool The pool that the element will be managed within
+ * @param element The element we are caching
+ */
+ @SuppressWarnings("unchecked")
+ public CachedElement(Pool<T> pool, T element) {
+ this.pool = pool;
+ this.element = element;
+
+ try {
+ pool.release((T) this);
+ } catch (PoolDrainedException e) {
+ LOG.error("Pool is empty", e);
+ }
+ }
+
+ /**
+ * This method delegates the close call to the actual wrapped element.
+ * <p>
+ * NOTE: This is not the same method that is called by the dynamic proxy. This method is in
+ * place to satisfy the signature of the {@link Closeable} interface. If it were to be
+ * called directly, then we will delegate the close to the underlying context. However, when the
+ * cached element is called as a synamic proxy, entry is in the
+ * {@link #invoke(Object, Method, Object[])} method.
+ * </p>
+ *
+ * @see Closeable#close()
+ */
+ @Override
+ public void close() throws IOException {
+ element.close();
+ }
+
+ /**
+ * This method is the magic part of dynamic proxies. When the caller makes a method call based
+ * on the interface being proxied, this method is given control. This informs us of the method
+ * and arguments of the call. The object reference is that of the dynamic proxy itself, which is
+ * us.
+ * <p>
+ * Here we will check to see if the user is trying to close the "element" (the dynamic proxy
+ * acts like the wrapped element). If he is, then we don't really close it, but instead release
+ * the element that we are wrapping back to the free pool. Once this has happened, we mark the
+ * element as "closed" (from the perspective of this dynamic proxy) so that we wont try to
+ * release it again.
+ * </p>
+ * <p>
+ * If the method is the <code>equals</code> method then we assume that we are comparing the
+ * cached element in one dynamic proxy to the cached element in another. We execute the
+ * comparison between the cached elements, and not the dynamic proxies themselves. This
+ * preserves the allusion to the caller that the dynamic proxy is the object being wrapped.
+ * </p>
+ * <p>
+ * For convenience, we also implement the <code>getWrappedObject</code> method so that the
+ * dynamic proxy can be called to obtain the actual wrapped object if desired. Note, to use this
+ * method, the caller would have to invoke it through reflection.
+ * </p>
+ * <p>
+ * If the method being invoked is not one that we intercept, then we simply delegate that method
+ * onto the wrapped object.
+ * </p>
+ *
+ * @see InvocationHandler#invoke(Object, Method,
+ * Object[])
+ */
+ @SuppressWarnings({"unchecked", "nls"})
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
+ Object result = null;
+
+ switch (method.getName()) {
+ case "close":
+ if (released.compareAndSet(false, true) && !pool.isDrained()) {
+ pool.release((T) proxy);
+ }
+ break;
+ case "equals":
+ CacheManagement cm = (CacheManagement) proxy;
+ T other = (T) cm.getWrappedObject();
+ result = element.equals(other);
+ break;
+ case "getWrappedObject":
+ return element;
+ default:
+ result = method.invoke(element, args);
+ break;
+ }
+
+ return result;
+ }
+
+ /**
+ * This method is used to be able to access the wrapped object underneath the dynamic proxy
+ *
+ * @see org.onap.ccsdk.sli.core.utils.pool.CacheManagement#getWrappedObject()
+ */
+ @Override
+ public T getWrappedObject() {
+ return element;
+ }
+
+ @SuppressWarnings("nls")
+ @Override
+ public String toString() {
+ return element == null ? "null" : element.toString();
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Destructor.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Destructor.java
new file mode 100644
index 000000000..10d94e13d
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Destructor.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+import java.io.Closeable;
+
+/**
+ * @param <T>
+ * The generic type we are caching
+ */
+
+public interface Destructor<T extends Closeable> {
+
+ /**
+ * Called to destroy the object when it is no longer being used by the pool
+ *
+ * @param obj
+ * The object to be destroyed
+ * @param pool
+ * The pool that the object is being removed from
+ */
+ void destroy(T obj, Pool<T> pool);
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Pool.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Pool.java
new file mode 100644
index 000000000..8ebdc8575
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/Pool.java
@@ -0,0 +1,368 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+import java.io.Closeable;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * This class is used to manage a pool of things.
+ * <p>
+ * The class is parameterized so that the type of objects maintained in the pool is definable by some provided type.
+ * This type must implement the <code>Comparable</code> interface so that it can be managed in the pool.
+ * </p>
+ *
+ * @param <T>
+ * The type of element being pooled
+ */
+
+public class Pool<T extends Closeable> {
+ private Deque<T> free;
+ private List<T> allocated;
+ private int minPool;
+ private int maxPool;
+ private Allocator<T> allocator;
+ private org.onap.ccsdk.sli.core.utils.pool.Destructor<T> destructor;
+ private ReadWriteLock lock;
+ private AtomicBoolean drained;
+ private Properties properties;
+
+ /**
+ * Create the pool
+ *
+ * @param minPool
+ * The minimum size of the pool
+ * @param maxPool
+ * The maximum size of the pool, set to zero (0) for unbounded
+ * @throws PoolSpecificationException
+ * If the minimum size is less than 0, or if the max size is non-zero and less than the min size.
+ */
+ public Pool(int minPool, int maxPool) throws PoolSpecificationException {
+
+ if (minPool < 0) {
+ throw new PoolSpecificationException(String.format("The minimum pool size must be a "
+ + "positive value or zero, %d is not valid.", minPool));
+ }
+ if (maxPool != 0 && maxPool < minPool) {
+ throw new PoolSpecificationException(String.format("The maximum pool size must be a "
+ + "positive value greater than the minimum size, or zero. %d is not valid.", maxPool));
+ }
+
+ this.minPool = minPool;
+ this.maxPool = maxPool;
+
+ properties = new Properties();
+ free = new ArrayDeque<T>();
+ allocated = new ArrayList<T>();
+ lock = new ReentrantReadWriteLock();
+ drained = new AtomicBoolean(false);
+ }
+
+ /**
+ * Returns the amount of objects on the free collection
+ *
+ * @return The number of objects on the free collection
+ */
+ public int getFreeSize() {
+ Lock readLock = lock.readLock();
+ readLock.lock();
+ try {
+ return free.size();
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the value for a specified property of this pool, if defined.
+ *
+ * @param key
+ * The key of the desired property
+ * @return The value of the property, or null if not defined
+ */
+ public String getProperty(String key) {
+ return properties.getProperty(key);
+ }
+
+ /**
+ * Sets the value of the specified property or replaces it if it already exists
+ *
+ * @param key
+ * The key of the property to be set
+ * @param value
+ * The value to set the property to
+ */
+ public void setProperty(String key, String value) {
+ properties.setProperty(key, value);
+ }
+
+ /**
+ * @return The properties object for the pool
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Returns the number of objects that are currently allocated
+ *
+ * @return The allocate collection size
+ */
+ public int getAllocatedSize() {
+ Lock readLock = lock.readLock();
+ readLock.lock();
+ try {
+ return allocated.size();
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ /**
+ * @return the value of allocator
+ */
+ public Allocator<T> getAllocator() {
+ return allocator;
+ }
+
+ /**
+ * @param allocator
+ * the value for allocator
+ */
+ public void setAllocator(Allocator<T> allocator) {
+ this.allocator = allocator;
+ }
+
+ /**
+ * @return the value of destructor
+ */
+ public org.onap.ccsdk.sli.core.utils.pool.Destructor<T> getDestructor() {
+ return destructor;
+ }
+
+ /**
+ * @return the value of minPool
+ */
+ public int getMinPool() {
+ return minPool;
+ }
+
+ /**
+ * @return the value of maxPool
+ */
+ public int getMaxPool() {
+ return maxPool;
+ }
+
+ /**
+ * @param destructor
+ * the value for destructor
+ */
+ public void setDestructor(org.onap.ccsdk.sli.core.utils.pool.Destructor<T> destructor) {
+ this.destructor = destructor;
+ }
+
+ /**
+ * Drains the pool, releasing and destroying all pooled objects, even if they are currently allocated.
+ */
+ public void drain() {
+ if (drained.compareAndSet(false, true)) {
+ Lock writeLock = lock.writeLock();
+ writeLock.lock();
+ try {
+ int size = getAllocatedSize();
+ /*
+ * We can't use the "release" method call here because we are modifying the list we are iterating
+ */
+ ListIterator<T> it = allocated.listIterator();
+ while (it.hasNext()) {
+ T obj = it.next();
+ it.remove();
+ free.addFirst(obj);
+ }
+ size = getFreeSize();
+ trim(size);
+ } finally {
+ writeLock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Returns an indication if the pool has been drained
+ *
+ * @return True indicates that the pool has been drained. Once a pool has been drained, it can no longer be used.
+ */
+ public boolean isDrained() {
+ return drained.get();
+ }
+
+ /**
+ * Reserves an object of type T from the pool for the caller and returns it
+ *
+ * @return The object of type T to be used by the caller
+ * @throws org.onap.ccsdk.sli.core.utils.pool.PoolExtensionException
+ * If the pool cannot be extended
+ * @throws org.onap.ccsdk.sli.core.utils.pool.PoolDrainedException
+ * If the caller is trying to reserve an element from a drained pool
+ */
+ @SuppressWarnings("unchecked")
+ public T reserve() throws org.onap.ccsdk.sli.core.utils.pool.PoolExtensionException, org.onap.ccsdk.sli.core.utils.pool.PoolDrainedException {
+ if (isDrained()) {
+ throw new org.onap.ccsdk.sli.core.utils.pool.PoolDrainedException("The pool has been drained and cannot be used.");
+ }
+
+ T obj = null;
+ Lock writeLock = lock.writeLock();
+ writeLock.lock();
+ try {
+ int freeSize = getFreeSize();
+ int allocatedSize = getAllocatedSize();
+
+ if (freeSize == 0) {
+ if (allocatedSize == 0) {
+ extend(minPool == 0 ? 1 : minPool);
+ } else if (allocatedSize >= maxPool && maxPool > 0) {
+ throw new org.onap.ccsdk.sli.core.utils.pool.PoolExtensionException(String.format("Unable to add "
+ + "more elements, pool is at maximum size of %d", maxPool));
+ } else {
+ extend(1);
+ }
+ }
+
+ obj = free.removeFirst();
+ allocated.add(obj);
+ } finally {
+ writeLock.unlock();
+ }
+
+ /*
+ * Now that we have the real object, lets wrap it in a dynamic proxy so that we can intercept the close call and
+ * just return the context to the free pool. obj.getClass().getInterfaces(). We need to find ALL interfaces that
+ * the object (and all superclasses) implement and have the proxy implement them too
+ */
+ Class<?> cls = obj.getClass();
+ Class<?>[] array;
+ List<Class<?>> interfaces = new ArrayList<Class<?>>();
+ while (!cls.equals(Object.class)) {
+ array = cls.getInterfaces();
+ for (Class<?> item : array) {
+ if (!interfaces.contains(item)) {
+ interfaces.add(item);
+ }
+ }
+ cls = cls.getSuperclass();
+ }
+ array = new Class<?>[interfaces.size()];
+ array = interfaces.toArray(array);
+ return org.onap.ccsdk.sli.core.utils.pool.CachedElement.newInstance(this, obj, array);
+ }
+
+ /**
+ * releases the allocated object back to the free pool to be used by another request.
+ *
+ * @param obj
+ * The object to be returned to the pool
+ * @throws org.onap.ccsdk.sli.core.utils.pool.PoolDrainedException
+ * If the caller is trying to release an element to a drained pool
+ */
+ public void release(T obj) throws org.onap.ccsdk.sli.core.utils.pool.PoolDrainedException {
+ if (isDrained()) {
+ throw new org.onap.ccsdk.sli.core.utils.pool.PoolDrainedException("The pool has been drained and cannot be used.");
+ }
+ Lock writeLock = lock.writeLock();
+ writeLock.lock();
+ try {
+ if (allocated.remove(obj)) {
+ free.addFirst(obj);
+ }
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ /**
+ * Extend the free pool by some number of elements
+ *
+ * @param count
+ * The number of elements to add to the pool
+ * @throws org.onap.ccsdk.sli.core.utils.pool.PoolExtensionException
+ * if the pool cannot be extended because no allocator has been specified.
+ */
+ private void extend(int count) throws org.onap.ccsdk.sli.core.utils.pool.PoolExtensionException {
+ if (allocator == null) {
+ throw new org.onap.ccsdk.sli.core.utils.pool.PoolExtensionException(String.format("Unable to extend pool "
+ + "because no allocator has been specified"));
+ }
+ Lock writeLock = lock.writeLock();
+ writeLock.lock();
+ try {
+ for (int index = 0; index < count; index++) {
+ T obj = allocator.allocate(this);
+ if (obj == null) {
+ throw new org.onap.ccsdk.sli.core.utils.pool.PoolExtensionException(
+ "The allocator failed to allocate a new context to extend the pool.");
+ }
+ free.push(obj);
+ }
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ /**
+ * Used to trim the free collection by some specified number of elements, or the free element count, whichever is
+ * less. The elements are removed from the end of the free element deque, thus trimming the oldest elements first.
+ *
+ * @param count
+ * The number of elements to trim
+ */
+ private void trim(int count) {
+ Lock writeLock = lock.writeLock();
+ writeLock.lock();
+ try {
+ int trimCount = count;
+ if (getFreeSize() < count) {
+ trimCount = getFreeSize();
+ }
+ for (int i = 0; i < trimCount; i++) {
+ T obj = free.removeLast();
+ if (destructor != null) {
+ destructor.destroy(obj, this);
+ }
+ }
+ } finally {
+ writeLock.unlock();
+ }
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolDrainedException.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolDrainedException.java
new file mode 100644
index 000000000..163298e49
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolDrainedException.java
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+/**
+ * This exception is thrown whenever an attempt is made to access a pool of resources where the pool has been drained.
+ * Once drained, the pool is no longer usable.
+ *
+ */
+public class PoolDrainedException extends PoolException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * PoolDrainedException constructor
+ *
+ * @param msg
+ * The error message
+ */
+ public PoolDrainedException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolException.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolException.java
new file mode 100644
index 000000000..110d08bba
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolException.java
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+/**
+ * A pool exception is a specialization of checked exceptions that define various pool abnormal states or requests.
+ *
+ */
+public class PoolException extends Exception {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * PoolException constructor
+ */
+ public PoolException() {
+ }
+
+ /**
+ * PoolException constructor
+ *
+ * @param message
+ * The error message
+ */
+ public PoolException(String message) {
+ super(message);
+ }
+
+ /**
+ * PoolException constructor
+ *
+ * @param cause
+ * The cause of the exception
+ */
+ public PoolException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * PoolException constructor
+ *
+ * @param message
+ * The error message
+ * @param cause
+ * The cause of the exception
+ */
+ public PoolException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * PoolException constructor
+ *
+ * @param message
+ * The error message
+ * @param cause
+ * The cause of the exception
+ * @param enableSuppression
+ * whether or not suppression is enabled or disabled
+ * @param writableStackTrace
+ * whether or not the stack trace should be writable
+ */
+ public PoolException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolExtensionException.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolExtensionException.java
new file mode 100644
index 000000000..c326197fb
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolExtensionException.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+/**
+ * An error occurred trying to extend the pool
+ *
+ */
+public class PoolExtensionException extends org.onap.ccsdk.sli.core.utils.pool.PoolException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * PoolExtensionException constructor
+ *
+ * @param msg
+ * The error message
+ */
+ public PoolExtensionException(String msg) {
+ super(msg);
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolSpecificationException.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolSpecificationException.java
new file mode 100644
index 000000000..3bc5f51e6
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/pool/PoolSpecificationException.java
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+/**
+ * This exception is thrown whenever the pool is not specified correctly
+ *
+ */
+public class PoolSpecificationException extends org.onap.ccsdk.sli.core.utils.pool.PoolException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * PoolSpecificationException constructor
+ *
+ * @param msg
+ * The error message
+ */
+ public PoolSpecificationException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/logging/LoggingConstantsTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/logging/LoggingConstantsTest.java
new file mode 100644
index 000000000..e8767a550
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/logging/LoggingConstantsTest.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.logging;
+
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+public class LoggingConstantsTest {
+ @Test (expected = IllegalAccessError.class)
+ public void testConstructor() throws Exception {
+ Whitebox.invokeConstructor(LoggingConstants.class);
+ }
+
+ @Test (expected = IllegalAccessError.class)
+ public void testMdcKeysConstructor() throws Exception {
+ Whitebox.invokeConstructor(LoggingConstants.MDCKeys.class);
+ }
+
+ @Test (expected = IllegalAccessError.class)
+ public void testStatusCodesConstructor() throws Exception {
+ Whitebox.invokeConstructor(LoggingConstants.StatusCodes.class);
+ }
+
+ @Test (expected = IllegalAccessError.class)
+ public void testTargetNamesConstructor() throws Exception {
+ Whitebox.invokeConstructor(LoggingConstants.TargetNames.class);
+ }
+
+ @Test (expected = IllegalAccessError.class)
+ public void testTargetServiceNamesConstructor() throws Exception {
+ Whitebox.invokeConstructor(LoggingConstants.TargetServiceNames.class);
+ }
+
+ @Test (expected = IllegalAccessError.class)
+ public void testAAIServiceNamesConstructor() throws Exception {
+ Whitebox.invokeConstructor(LoggingConstants.TargetServiceNames.AAIServiceNames.class);
+ }
+}
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/logging/LoggingUtilsTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/logging/LoggingUtilsTest.java
new file mode 100644
index 000000000..3c1708b42
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/logging/LoggingUtilsTest.java
@@ -0,0 +1,357 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 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.
+ * 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.ccsdk.sli.core.utils.logging;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.lang.reflect.Method;
+import java.time.Instant;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+import org.slf4j.MDC;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+public class LoggingUtilsTest {
+ @Test(expected = IllegalAccessError.class)
+ public void testConstructor() throws Exception {
+ Whitebox.invokeConstructor(LoggingUtils.class);
+ }
+
+ @Test
+ public void testLogErrorMessageStringStringStringStringStringString() {
+ try {
+ LoggingUtils.logErrorMessage("ERROR_CODE", "ERROR_DESCRIPTION", "TARGET_ENTITY", "TARGET_SERVICE_NAME", "ADDITIONAL_MESSAGE", "CLASS_NAME");
+ assertNull(MDC.get(LoggingConstants.MDCKeys.CLASS_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking logErrorMessage: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testLogErrorMessageStringStringStringString() {
+ try {
+ LoggingUtils.logErrorMessage("TARGET_ENTITY", "TARGET_SERVICE_NAME", "ADDITIONAL_MESSAGE", "CLASS_NAME");
+ assertNull(MDC.get(LoggingConstants.MDCKeys.CLASS_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking logErrorMessage: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testLogErrorMessageStringStringString() {
+ try {
+ LoggingUtils.logErrorMessage("TARGET_SERVICE_NAME", "ADDITIONAL_MESSAGE", "CLASS_NAME");
+ assertNull(MDC.get(LoggingConstants.MDCKeys.CLASS_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking logErrorMessage: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testLogError() {
+ try {
+ Class<?>[] paramString = { String.class, String.class, String.class, String.class, String.class, String.class };
+ Method m = LoggingUtils.class.getDeclaredMethod("logError", paramString);
+ m.setAccessible(true);
+ m.invoke(null, "ERROR_CODE", "ERROR_DESCRIPTION", "TARGET_ENTITY", "TARGET_SERVICE_NAME", "ADDITIONAL_MESSAGE", "CLASS_NAME");
+ assertNull(MDC.get(LoggingConstants.MDCKeys.CLASS_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking logError: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testLogAuditMessage() {
+ try {
+ Class<?>[] paramString = { Instant.class, Instant.class, String.class, String.class, String.class };
+ Method m = LoggingUtils.class.getDeclaredMethod("logAuditMessage", paramString);
+ m.setAccessible(true);
+ java.util.Date timestamp = new java.util.Date();
+ m.invoke(null, timestamp.toInstant(), timestamp.toInstant(), "CODE", "RESPONSE_DESCRIPTION", "CLASS_NAME");
+ assertNull(MDC.get(LoggingConstants.MDCKeys.CLASS_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking logAuditMessage: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testAuditInfo() {
+ try {
+ EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
+ auditLogger.info("Audit logging test info");
+ } catch (Exception e) {
+ fail("Exception invoking testAuditInfo: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testAuditWarn() {
+ try {
+ EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
+ auditLogger.warn("Audit logging test warning");
+ } catch (Exception e) {
+ fail("Exception invoking testAuditWarn: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testLogMetricsMessage() {
+ try {
+ java.util.Date timestamp = new java.util.Date();
+ LoggingUtils.logMetricsMessage(timestamp.toInstant(), timestamp.toInstant(), "TARGET_ENTITY", "TARGET_SERVICE_NAME", "STATUS_CODE", "RESPONSE_CODE", "RESPONSE_DESCRIPTION", "CLASS_NAME");
+ assertNull(MDC.get(LoggingConstants.MDCKeys.STATUS_CODE));
+
+ } catch (Exception e) {
+ fail("Exception invoking logMetricsMessage: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testPopulateAuditLogContext() {
+ try {
+ Class<?>[] paramString = { Instant.class, Instant.class, String.class, String.class, String.class };
+ Method m = LoggingUtils.class.getDeclaredMethod("populateAuditLogContext", paramString);
+ m.setAccessible(true);
+ java.util.Date timestamp = new java.util.Date();
+ m.invoke(null, timestamp.toInstant(), timestamp.toInstant(), "100", "RESPONSE_DESCRIPTION", "CLASS_NAME");
+ assertEquals("COMPLETE", MDC.get(LoggingConstants.MDCKeys.STATUS_CODE));
+ assertEquals("100", MDC.get(LoggingConstants.MDCKeys.RESPONSE_CODE));
+ assertEquals("RESPONSE_DESCRIPTION", MDC.get(LoggingConstants.MDCKeys.RESPONSE_DESCRIPTION));
+ } catch (Exception e) {
+ fail("Exception invoking populateAuditLogContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testCleanAuditErrorContext() {
+ try {
+ Method m = LoggingUtils.class.getDeclaredMethod("cleanAuditErrorContext");
+ m.setAccessible(true);
+ MDC.put(LoggingConstants.MDCKeys.STATUS_CODE, "STATUS_CODE");
+ MDC.put(LoggingConstants.MDCKeys.RESPONSE_CODE, "RESPONSE_CODE");
+ MDC.put(LoggingConstants.MDCKeys.RESPONSE_DESCRIPTION, "RESPONSE_DESCRIPTION");
+ MDC.put(LoggingConstants.MDCKeys.CLASS_NAME, "CLASS_NAME");
+ m.invoke(null);
+ assertNull(MDC.get(LoggingConstants.MDCKeys.STATUS_CODE));
+ assertNull(MDC.get(LoggingConstants.MDCKeys.RESPONSE_CODE));
+ assertNull(MDC.get(LoggingConstants.MDCKeys.RESPONSE_DESCRIPTION));
+ assertNull(MDC.get(LoggingConstants.MDCKeys.CLASS_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking cleanAuditErrorLogContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testPopulateErrorLogContext() {
+ try {
+ Class<?>[] paramString = { String.class, String.class, String.class, String.class, String.class };
+ Method m = LoggingUtils.class.getDeclaredMethod("populateErrorLogContext", paramString);
+ m.setAccessible(true);
+ m.invoke(null, "ERROR_CODE", "ERROR_DESCRIPTION", "TARGET_ENTITY", "TARGET_SERVICENAME", "CLASS_NAME");
+ assertEquals("CLASS_NAME", MDC.get(LoggingConstants.MDCKeys.CLASS_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking populateErrorLogContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testCleanErrorLogContext() {
+ try {
+ Method m = LoggingUtils.class.getDeclaredMethod("cleanErrorLogContext");
+ m.setAccessible(true);
+ MDC.put(LoggingConstants.MDCKeys.CLASS_NAME, "CLASS_NAME");
+ m.invoke(null);
+ assertNull(MDC.get(LoggingConstants.MDCKeys.CLASS_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking cleanErrorLogContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testPopulateMetricLogContext() {
+ try {
+ Class<?>[] paramString = { Instant.class, Instant.class, String.class, String.class, String.class,
+ String.class, String.class, String.class };
+ Method m = LoggingUtils.class.getDeclaredMethod("populateMetricLogContext", paramString);
+ m.setAccessible(true);
+ java.util.Date timestamp = new java.util.Date();
+ m.invoke(null, timestamp.toInstant(), timestamp.toInstant(), "TARGET_ENTITY", "TARGET_SERVICE_NAME", "STATUS_CODE", "RESPONSE_CODE", "RESPONSE_DESCRIPTION", "CLASS_NAME");
+ assertEquals("STATUS_CODE", MDC.get(LoggingConstants.MDCKeys.STATUS_CODE));
+ assertEquals("RESPONSE_CODE", MDC.get(LoggingConstants.MDCKeys.RESPONSE_CODE));
+ assertEquals("RESPONSE_DESCRIPTION", MDC.get(LoggingConstants.MDCKeys.RESPONSE_DESCRIPTION));
+ } catch (Exception e) {
+ fail("Exception invoking populateMetricLogContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testCleanMetricContext() {
+ try {
+ Method m = LoggingUtils.class.getDeclaredMethod("cleanMetricContext");
+ m.setAccessible(true);
+ MDC.put(LoggingConstants.MDCKeys.CLASS_NAME, "CLASS_NAME");
+ m.invoke(null);
+ assertNull(MDC.get(LoggingConstants.MDCKeys.CLASS_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking cleanMetricContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testPopulateTargetContext() {
+ try {
+ Class<?>[] paramString = { String.class, String.class };
+ Method m = LoggingUtils.class.getDeclaredMethod("populateTargetContext", paramString);
+ m.setAccessible(true);
+ m.invoke(null, "TARGET_ENTITY", "TARGET_SERVICE_NAME");
+ assertEquals("TARGET_ENTITY", MDC.get(LoggingConstants.MDCKeys.TARGET_ENTITY));
+ assertEquals("TARGET_SERVICE_NAME", MDC.get(LoggingConstants.MDCKeys.TARGET_SERVICE_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking populateTargetContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testCleanTargetContext() {
+ try {
+ Method m = LoggingUtils.class.getDeclaredMethod("cleanTargetContext");
+ m.setAccessible(true);
+ MDC.put(LoggingConstants.MDCKeys.TARGET_ENTITY, "TARGET_ENTITY");
+ MDC.put(LoggingConstants.MDCKeys.TARGET_SERVICE_NAME, "TARGET_SERVICE_NAME");
+ m.invoke(null);
+ assertNull(MDC.get(LoggingConstants.MDCKeys.TARGET_ENTITY));
+ assertNull(MDC.get(LoggingConstants.MDCKeys.TARGET_SERVICE_NAME));
+ } catch (Exception e) {
+ fail("Exception invoking cleanTargetContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testPopulateTimeContext() {
+ try {
+ Class<?>[] paramString = { Instant.class, Instant.class };
+ Method m = LoggingUtils.class.getDeclaredMethod("populateTimeContext", paramString);
+ m.setAccessible(true);
+ java.util.Date timestamp = new java.util.Date();
+ m.invoke(null, timestamp.toInstant(), timestamp.toInstant());
+ } catch (Exception e) {
+ fail("Exception invoking populateTimeContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testGenerateTimestampStr() {
+ try {
+ Class<?>[] paramString = { Instant.class };
+ Method m = LoggingUtils.class.getDeclaredMethod("generateTimestampStr", paramString);
+ m.setAccessible(true);
+ java.util.Date timestamp = new java.util.Date();
+ assertNotNull((String) m.invoke(null, timestamp.toInstant()));
+ } catch (Exception e) {
+ fail("Exception invoking testGenerateTimestampStr: " + e.toString());
+ }
+
+ }
+
+ @Test
+ public void testCleanTimeContext() {
+ try {
+ Method m = LoggingUtils.class.getDeclaredMethod("cleanTimeContext");
+ m.setAccessible(true);
+ MDC.put(LoggingConstants.MDCKeys.BEGIN_TIMESTAMP, "BEGIN_TIMESTAMP");
+ MDC.put(LoggingConstants.MDCKeys.END_TIMESTAMP, "END_TIMESTAMP");
+ MDC.put(LoggingConstants.MDCKeys.ELAPSED_TIME, "ELAPSED_TIME");
+ m.invoke(null);
+ assertNull(MDC.get(LoggingConstants.MDCKeys.BEGIN_TIMESTAMP));
+ assertNull(MDC.get(LoggingConstants.MDCKeys.END_TIMESTAMP));
+ assertNull(MDC.get(LoggingConstants.MDCKeys.ELAPSED_TIME));
+ } catch (Exception e) {
+ fail("Exception invoking cleanErrorContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testPopulateResponseContext() {
+ try {
+ Class<?>[] paramString = { String.class, String.class, String.class };
+ Method m = LoggingUtils.class.getDeclaredMethod("populateResponseContext", paramString);
+ m.setAccessible(true);
+ m.invoke(null, "STATUS_CODE", "RESPONSE_CODE", "RESPONSE_DESCRIPTION");
+ assertEquals("STATUS_CODE", MDC.get(LoggingConstants.MDCKeys.STATUS_CODE));
+ assertEquals("RESPONSE_CODE", MDC.get(LoggingConstants.MDCKeys.RESPONSE_CODE));
+ assertEquals("RESPONSE_DESCRIPTION", MDC.get(LoggingConstants.MDCKeys.RESPONSE_DESCRIPTION));
+ } catch (Exception e) {
+ fail("Exception invoking populateResponseContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testCleanResponseContext() {
+ try {
+ Method m = LoggingUtils.class.getDeclaredMethod("cleanResponseContext");
+ m.setAccessible(true);
+ MDC.put(LoggingConstants.MDCKeys.STATUS_CODE, "STATUS_CODE");
+ MDC.put(LoggingConstants.MDCKeys.RESPONSE_CODE, "RESPONSE_CODE");
+ MDC.put(LoggingConstants.MDCKeys.RESPONSE_DESCRIPTION, "RESPONSE_DESCRIPTION");
+ m.invoke(null);
+ assertNull(MDC.get(LoggingConstants.MDCKeys.STATUS_CODE));
+ assertNull(MDC.get(LoggingConstants.MDCKeys.RESPONSE_CODE));
+ assertNull(MDC.get(LoggingConstants.MDCKeys.RESPONSE_DESCRIPTION));
+ } catch (Exception e) {
+ fail("Exception invoking cleanErrorContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testPopulateErrorContext() {
+ try {
+ Class<?>[] paramString = { String.class, String.class };
+ Method m = LoggingUtils.class.getDeclaredMethod("populateErrorContext", paramString);
+ m.setAccessible(true);
+ m.invoke(null, "ERROR_CODE", "ERROR_DESCRIPTION");
+ //assertEquals("900", MDC.get(LoggingConstants.MDCKeys.ERROR_CODE));
+ assertEquals("ERROR_DESCRIPTION", MDC.get(LoggingConstants.MDCKeys.ERROR_DESCRIPTION));
+ } catch (Exception e) {
+ fail("Exception invoking populateErrorContext: " + e.toString());
+ }
+ }
+
+ @Test
+ public void testCleanErrorContext() {
+ try {
+ Method m = LoggingUtils.class.getDeclaredMethod("cleanErrorContext");
+ m.setAccessible(true);
+ MDC.put(LoggingConstants.MDCKeys.ERROR_CODE, "ERROR_CODE");
+ MDC.put(LoggingConstants.MDCKeys.ERROR_DESCRIPTION, "ERROR_DESCRIPTION");
+ m.invoke(null);
+ assertNull(MDC.get(LoggingConstants.MDCKeys.ERROR_CODE));
+ assertNull(MDC.get(LoggingConstants.MDCKeys.ERROR_DESCRIPTION));
+ } catch (Exception e) {
+ fail("Exception invoking cleanErrorContext: " + e.toString());
+ }
+ }
+
+}
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/CachedElementTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/CachedElementTest.java
new file mode 100644
index 000000000..60fd6f570
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/CachedElementTest.java
@@ -0,0 +1,285 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Modifications Copyright (C) 2019 IBM
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+public class CachedElementTest implements Allocator<Testable>, Destructor<Testable> {
+ private static final int MIN = 10;
+ private static final int MAX = 100;
+ private Pool<Testable> pool;
+ private int index = 0;
+ private int destroyCount = 0;
+
+ /**
+ * setup
+ *
+ * @throws PoolSpecificationException
+ * If the minimum size is less than 0, or if the max size is non-zero and less than the min size.
+ */
+ @Before
+ public void setup() throws PoolSpecificationException {
+ pool = new Pool<>(MIN, MAX);
+ }
+
+ /**
+ * Test state
+ */
+ @Test
+ public void testAllocator() {
+ assertNull(pool.getAllocator());
+ pool.setAllocator(this);
+ assertNotNull(pool.getAllocator());
+ }
+
+ /**
+ * Test state
+ */
+ @Test
+ public void testDestructor() {
+ assertNull(pool.getDestructor());
+ pool.setDestructor(this);
+ assertNotNull(pool.getDestructor());
+ }
+
+ /**
+ * Test that we can allocate and release elements and that the pool maintains them in MRU order
+ *
+ * @throws PoolExtensionException
+ * If the pool cannot be extended
+ * @throws PoolDrainedException
+ * If the caller is trying to reserve an element from a drained pool
+ */
+ @Test
+ public void testAllocateAndRelease() throws PoolExtensionException, PoolDrainedException {
+ pool.setAllocator(this);
+
+ assertFalse(pool.isDrained());
+
+ /*
+ * Allocate three elements
+ */
+ Testable value1 = pool.reserve();
+ assertNotNull(value1);
+ assertEquals(Integer.valueOf(MIN - 1), Integer.valueOf(value1.getId()));
+ assertEquals(1, pool.getAllocatedSize());
+ assertEquals(MIN - 1, pool.getFreeSize());
+ assertEquals(1, pool.getAllocatedSize());
+
+ Testable value2 = pool.reserve();
+ assertNotNull(value2);
+ assertEquals(Integer.valueOf(MIN - 2), Integer.valueOf(value2.getId()));
+ assertEquals(2, pool.getAllocatedSize());
+ assertEquals(MIN - 2, pool.getFreeSize());
+ assertEquals(2, pool.getAllocatedSize());
+
+ Testable value3 = pool.reserve();
+ assertNotNull(value3);
+ assertEquals(Integer.valueOf(MIN - 3), Integer.valueOf(value3.getId()));
+ assertEquals(3, pool.getAllocatedSize());
+ assertEquals(MIN - 3, pool.getFreeSize());
+ assertEquals(3, pool.getAllocatedSize());
+
+ /*
+ * Now, release them in the order obtained
+ */
+ pool.release(value1);
+ pool.release(value2);
+ pool.release(value3);
+
+ assertEquals(0, pool.getAllocatedSize());
+ assertEquals(MIN, pool.getFreeSize());
+
+ /*
+ * Now, allocate them again, but their values should be reversed (3, 2, 1) representing the most recently used
+ * to the least recently used.
+ */
+ value1 = pool.reserve();
+ assertNotNull(value1);
+ assertEquals(Integer.valueOf(MIN - 3), Integer.valueOf(value1.getId()));
+
+ value2 = pool.reserve();
+ assertNotNull(value2);
+ assertEquals(Integer.valueOf(MIN - 2), Integer.valueOf(value2.getId()));
+
+ value3 = pool.reserve();
+ assertNotNull(value3);
+ assertEquals(Integer.valueOf(MIN - 1), Integer.valueOf(value3.getId()));
+ }
+
+ /**
+ * Test that we can trim the pool to a desired size
+ *
+ * @throws PoolDrainedException
+ * If the caller is trying to release or reserve an element from a drained pool
+ * @throws PoolExtensionException
+ * If the pool cannot be extended
+ * @throws IllegalAccessException
+ * if this Method object is enforcing Java language access control and the underlying method is
+ * inaccessible.
+ * @throws IllegalArgumentException
+ * if the method is an instance method and the specified object argument is not an instance of the class
+ * or interface declaring the underlying method (or of a subclass or implementor thereof); if the number
+ * of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or
+ * if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal
+ * parameter type by a method invocation conversion.
+ * @throws InvocationTargetException
+ * if the underlying method throws an exception.
+ * @throws SecurityException
+ * If a security manager, s, is present and any of the following conditions is met:
+ * <ul>
+ * <li>invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared method</li>
+ * <li>the caller's class loader is not the same as or an ancestor of the class loader for the current
+ * class and invocation of s.checkPackageAccess() denies access to the package of this class</li>
+ * </ul>
+ * @throws NoSuchMethodException
+ * if a matching method is not found.
+ */
+ @SuppressWarnings("nls")
+ @Test
+ public void testTrim() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException,
+ PoolDrainedException, PoolExtensionException, NoSuchMethodException, SecurityException {
+
+ pool.setAllocator(this);
+ int SIZE = 50;
+ Testable[] array = new Testable[SIZE];
+
+ assertEquals(0, pool.getAllocatedSize());
+ for (int i = 0; i < SIZE; i++) {
+ array[i] = pool.reserve();
+ }
+ assertEquals(SIZE, pool.getAllocatedSize());
+
+ for (int i = 0; i < SIZE; i++) {
+ pool.release(array[i]);
+ }
+ assertEquals(0, pool.getAllocatedSize());
+
+ assertEquals(SIZE, pool.getFreeSize());
+
+ Method trimMethod = Pool.class.getDeclaredMethod("trim", new Class[] {
+ Integer.TYPE
+ });
+ trimMethod.setAccessible(true);
+ trimMethod.invoke(pool, new Object[] {
+ SIZE - MIN
+ });
+
+ assertEquals(MIN, pool.getFreeSize());
+ }
+
+ /**
+ * Test that we can drain a pool containing a mix of free and allocated elements
+ *
+ * @throws PoolDrainedException
+ * If the caller is trying to release or reserve an element from a drained pool
+ * @throws PoolExtensionException
+ * If the pool cannot be extended
+ * @throws IOException
+ * if an I/O error occurs
+ */
+ @Test
+ public void testDrain() throws PoolExtensionException, PoolDrainedException, IOException {
+ int SIZE = 50;
+ int FREE = 20;
+ int ALLOC = SIZE - FREE;
+
+ Testable[] array = new Testable[SIZE];
+ pool.setAllocator(this);
+ pool.setDestructor(this);
+
+ assertFalse(pool.isDrained());
+
+ assertEquals(0, pool.getAllocatedSize());
+ for (int i = 0; i < SIZE; i++) {
+ array[i] = pool.reserve();
+ }
+ assertEquals(SIZE, pool.getAllocatedSize());
+
+ for (int i = 0; i < FREE; i++) {
+ array[i].close();
+ }
+ assertEquals(ALLOC, pool.getAllocatedSize());
+ assertEquals(FREE, pool.getFreeSize());
+
+ pool.drain();
+ assertEquals(0, pool.getFreeSize());
+ assertEquals(0, pool.getAllocatedSize());
+ assertTrue(pool.isDrained());
+
+ assertEquals(SIZE, destroyCount);
+ }
+
+ /**
+ * @see org.onap.ccsdk.sli.core.utils.pool.Allocator#allocate(org.onap.ccsdk.sli.core.utils.pool.Pool)
+ */
+ @Override
+ public Testable allocate(Pool<Testable> pool) {
+ Testable element = new org.onap.ccsdk.sli.core.utils.pool.Element(index++);
+ Testable ce = CachedElement.newInstance(pool, element, new Class[] {
+ Testable.class
+ });
+ return ce;
+ }
+
+ /**
+ * @see org.onap.ccsdk.sli.core.utils.pool.Destructor#destroy(java.io.Closeable, org.onap.ccsdk.sli.core.utils.pool.Pool)
+ */
+ @Override
+ public void destroy(Testable obj, Pool<Testable> pool) {
+ destroyCount++;
+ }
+
+ @Test
+ public void testGetWrappedObject()
+ {
+ Testable element = new org.onap.ccsdk.sli.core.utils.pool.Element(index++);
+ CachedElement cachedElement = new CachedElement(pool, element);
+ assertNotNull(cachedElement.getWrappedObject());
+ assertSame(element, cachedElement.getWrappedObject());
+ }
+
+ @Test
+ public void testToString()
+ {
+ Testable element = new org.onap.ccsdk.sli.core.utils.pool.Element(index++);
+ CachedElement cachedElement = new CachedElement(pool, element);
+ assertTrue(cachedElement.toString() instanceof String);
+ }
+}
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/Element.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/Element.java
new file mode 100644
index 000000000..288a5ffbd
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/Element.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+import java.io.IOException;
+
+public class Element implements Testable {
+ private boolean closed;
+ private Integer id;
+
+ public Element(int id) {
+ this.id = Integer.valueOf(id);
+ closed = false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ boolean result = false;
+ if (obj instanceof Element) {
+ Element other = (Element) obj;
+ result = this.id.equals(other.id);
+ }
+
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ /**
+ * @see java.io.Closeable#close()
+ */
+ @Override
+ public void close() throws IOException {
+ closed = true;
+ }
+
+ @Override
+ public Boolean isClosed() {
+ return Boolean.valueOf(closed);
+ }
+
+ @Override
+ public String toString() {
+ return Integer.toString(id);
+ }
+
+ @Override
+ public Integer getId() {
+ return id;
+ }
+}
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolDrainedExceptionTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolDrainedExceptionTest.java
new file mode 100644
index 000000000..30907f995
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolDrainedExceptionTest.java
@@ -0,0 +1,35 @@
+/*-
+* ============LICENSE_START=======================================================
+* ONAP : APPC
+* ================================================================================
+* Copyright (C) 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.
+* 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.ccsdk.sli.core.utils.pool;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PoolDrainedExceptionTest {
+
+ @Test
+ public void testPoolDrainedException() {
+ String message = "test message";
+ PoolDrainedException poolDrainedExp = new PoolDrainedException(message);
+ Assert.assertEquals(message, poolDrainedExp.getMessage());
+ Assert.assertEquals(message, poolDrainedExp.getLocalizedMessage());
+ }
+
+}
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolExceptionTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolExceptionTest.java
new file mode 100644
index 000000000..9716d5813
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolExceptionTest.java
@@ -0,0 +1,72 @@
+/*-
+* ============LICENSE_START=======================================================
+* ONAP : APPC
+* ================================================================================
+* Copyright (C) 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.
+* 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.ccsdk.sli.core.utils.pool;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PoolExceptionTest {
+
+ @Test
+ public void testPoolException() {
+ PoolException poolException = new PoolException();
+ Assert.assertTrue(poolException.getCause() == null);
+ Assert.assertTrue(poolException.getMessage() == null);
+ }
+
+ @Test
+ public void testPoolExceptionString() {
+ String message = "test message";
+ PoolException poolException = new PoolException(message);
+ Assert.assertEquals(message, poolException.getMessage());
+ Assert.assertEquals(message, poolException.getLocalizedMessage());
+ }
+
+ @Test
+ public void testPoolExceptionThrowable() {
+ String tMessage = "throwable message";
+ Throwable throwable = new Throwable(tMessage);
+ PoolException poolException = new PoolException(throwable);
+ Assert.assertEquals(throwable, poolException.getCause());
+ }
+
+ @Test
+ public void testPoolExceptionStringThrowable() {
+ String message = "my test message";
+ String tMessage = "throwable message";
+ Throwable throwable = new Throwable(tMessage);
+ PoolException poolException = new PoolException(message, throwable);
+ Assert.assertEquals(throwable, poolException.getCause());
+ Assert.assertTrue(poolException.getMessage().contains(message));
+ Assert.assertEquals(message, poolException.getLocalizedMessage());
+ }
+
+ @Test
+ public void testPoolExceptionStringThrowableBooleanBoolean() {
+ String message = "my test message";
+ String tMessage = "throwable message";
+ Throwable throwable = new Throwable(tMessage);
+ PoolException poolException = new PoolException(message, throwable, true, true);
+ Assert.assertEquals(throwable, poolException.getCause());
+ Assert.assertTrue(poolException.getMessage().contains(message));
+ Assert.assertEquals(message, poolException.getLocalizedMessage());
+ }
+
+}
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolExtensionExceptionTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolExtensionExceptionTest.java
new file mode 100644
index 000000000..f972a7d4b
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolExtensionExceptionTest.java
@@ -0,0 +1,35 @@
+/*-
+* ============LICENSE_START=======================================================
+* ONAP : APPC
+* ================================================================================
+* Copyright (C) 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.
+* 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.ccsdk.sli.core.utils.pool;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PoolExtensionExceptionTest {
+
+ @Test
+ public void testPoolExtensionException() {
+ String message = "test message";
+ PoolExtensionException poolExtExcpt = new PoolExtensionException(message);
+ Assert.assertEquals(message, poolExtExcpt.getMessage());
+ Assert.assertEquals(message, poolExtExcpt.getLocalizedMessage());
+ }
+
+}
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolTest.java
new file mode 100644
index 000000000..c1c7aa199
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/PoolTest.java
@@ -0,0 +1,335 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Properties;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.utils.pool.*;
+import org.onap.ccsdk.sli.core.utils.pool.Allocator;
+import org.onap.ccsdk.sli.core.utils.pool.Destructor;
+import org.onap.ccsdk.sli.core.utils.pool.Pool;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class PoolTest implements Allocator<Testable>, Destructor<Testable> {
+
+ private Pool<Testable> pool;
+ private static final int MIN = 10;
+ private static final int MAX = 100;
+ private int index = 0;
+ private int destroyCount = 0;
+
+ /**
+ * Set up the test by allocating a pool with MIN-MAX size (bounded pool)
+ *
+ * @throws PoolSpecificationException
+ * If the minimum size is less than 0, or if the max size is non-zero and less than the min size.
+ */
+ @Before
+ public void setup() throws PoolSpecificationException {
+ pool = new Pool<>(MIN, MAX);
+ index = 0;
+ destroyCount = 0;
+ }
+
+ /**
+ * Test that trying to construct a pool with a bad minimum throws an exception
+ *
+ * @throws PoolSpecificationException
+ * If the minimum size is less than 0, or if the max size is non-zero and less than the min size.
+ */
+ @Test(expected = PoolSpecificationException.class)
+ public void testInvalidMinSize() throws PoolSpecificationException {
+ pool = new Pool<>(-1, MAX);
+ }
+
+ /**
+ * Test that trying to construct a pool with a bad maximum throws an exception
+ *
+ * @throws PoolSpecificationException
+ * If the minimum size is less than 0, or if the max size is non-zero and less than the min size.
+ */
+ @Test(expected = PoolSpecificationException.class)
+ public void testInvalidMaxSize() throws PoolSpecificationException {
+ pool = new Pool<>(MIN, -1);
+ }
+
+ /**
+ * Test creation of a pool where max is less than min fails
+ *
+ * @throws PoolSpecificationException
+ * If the minimum size is less than 0, or if the max size is non-zero and less than the min size.
+ */
+ @Test(expected = PoolSpecificationException.class)
+ public void testInvalidSizeRange() throws PoolSpecificationException {
+ pool = new Pool<>(MAX, MIN);
+ }
+
+ /**
+ * Test state
+ */
+ @Test
+ public void testMinPool() {
+ assertEquals(MIN, pool.getMinPool());
+ }
+
+ /**
+ * Test state
+ */
+ @Test
+ public void testMaxPool() {
+ assertEquals(MAX, pool.getMaxPool());
+ }
+
+ /**
+ * Test state
+ */
+ @Test
+ public void testAllocator() {
+ assertNull(pool.getAllocator());
+ pool.setAllocator(this);
+ assertNotNull(pool.getAllocator());
+ }
+
+ /**
+ * Test state
+ */
+ @Test
+ public void testDestructor() {
+ assertNull(pool.getDestructor());
+ pool.setDestructor(this);
+ assertNotNull(pool.getDestructor());
+ }
+
+ /**
+ * Test that we can allocate and release elements and that the pool maintains them in MRU order
+ *
+ * @throws PoolExtensionException
+ * If the pool cannot be extended
+ * @throws PoolDrainedException
+ * If the caller is trying to reserve an element from a drained pool
+ */
+ @Test
+ public void testAllocateAndRelease() throws PoolExtensionException, PoolDrainedException {
+ pool.setAllocator(this);
+
+ assertFalse(pool.isDrained());
+
+ /*
+ * Allocate three elements
+ */
+ Testable value1 = pool.reserve();
+ assertNotNull(value1);
+ assertEquals(Integer.valueOf(MIN - 1), value1.getId());
+ assertEquals(1, pool.getAllocatedSize());
+ assertEquals(MIN - 1, pool.getFreeSize());
+ assertEquals(1, pool.getAllocatedSize());
+
+ Testable value2 = pool.reserve();
+ assertNotNull(value2);
+ assertEquals(Integer.valueOf(MIN - 2), value2.getId());
+ assertEquals(2, pool.getAllocatedSize());
+ assertEquals(MIN - 2, pool.getFreeSize());
+ assertEquals(2, pool.getAllocatedSize());
+
+ Testable value3 = pool.reserve();
+ assertNotNull(value3);
+ assertEquals(Integer.valueOf(MIN - 3), value3.getId());
+ assertEquals(3, pool.getAllocatedSize());
+ assertEquals(MIN - 3, pool.getFreeSize());
+ assertEquals(3, pool.getAllocatedSize());
+
+ /*
+ * Now, release them in the order obtained
+ */
+ pool.release(value1);
+ pool.release(value2);
+ pool.release(value3);
+
+ assertEquals(0, pool.getAllocatedSize());
+ assertEquals(MIN, pool.getFreeSize());
+
+ /*
+ * Now, allocate them again, but their values should be reversed (3, 2, 1) representing the most recently used
+ * to the least recently used.
+ */
+ value1 = pool.reserve();
+ assertNotNull(value1);
+ assertEquals(Integer.valueOf(MIN - 3), value1.getId());
+
+ value2 = pool.reserve();
+ assertNotNull(value2);
+ assertEquals(Integer.valueOf(MIN - 2), value2.getId());
+
+ value3 = pool.reserve();
+ assertNotNull(value3);
+ assertEquals(Integer.valueOf(MIN - 1), value3.getId());
+ }
+
+ /**
+ * Test that we can trim the pool to a desired size
+ *
+ * @throws PoolExtensionException
+ * If the pool cannot be extended
+ * @throws NoSuchMethodException
+ * if a matching method is not found.
+ * @throws SecurityException
+ * if the request is denied.
+ * @throws IllegalAccessException
+ * if this Method object is enforcing Java language access control and the underlying method is
+ * inaccessible.
+ * @throws IllegalArgumentException
+ * if the method is an instance method and the specified object argument is not an instance of the class
+ * or interface declaring the underlying method (or of a subclass or implementor thereof); if the number
+ * of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or
+ * if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal
+ * parameter type by a method invocation conversion.
+ * @throws InvocationTargetException
+ * if the underlying method throws an exception.
+ * @throws PoolDrainedException
+ * If the caller is trying to reserve an element from a drained pool
+ */
+ @SuppressWarnings("nls")
+ @Test
+ public void testTrim() throws PoolExtensionException, NoSuchMethodException, SecurityException,
+ IllegalAccessException, IllegalArgumentException, InvocationTargetException, PoolDrainedException {
+ pool.setAllocator(this);
+ int SIZE = 50;
+ Proxy[] array = new Proxy[SIZE];
+
+ assertEquals(0, pool.getAllocatedSize());
+ for (int i = 0; i < SIZE; i++) {
+ array[i] = (Proxy) pool.reserve();
+ }
+ assertEquals(SIZE, pool.getAllocatedSize());
+
+ for (int i = 0; i < SIZE; i++) {
+ pool.release((Testable) array[i]);
+ }
+ assertEquals(0, pool.getAllocatedSize());
+
+ assertEquals(SIZE, pool.getFreeSize());
+
+ Method trimMethod = Pool.class.getDeclaredMethod("trim", new Class[] {
+ Integer.TYPE
+ });
+ trimMethod.setAccessible(true);
+ trimMethod.invoke(pool, new Object[] {
+ SIZE - MIN
+ });
+
+ assertEquals(MIN, pool.getFreeSize());
+ }
+
+ /**
+ * Test that we can drain a pool containing a mix of free and allocated elements
+ *
+ * @throws PoolExtensionException
+ * If the pool cannot be extended
+ * @throws PoolDrainedException
+ * If the caller is trying to reserve an element from a drained pool
+ */
+ @Test
+ public void testDrain() throws PoolExtensionException, PoolDrainedException {
+ int SIZE = 50;
+ int FREE = 20;
+ int ALLOC = SIZE - FREE;
+
+ Proxy[] array = new Proxy[SIZE];
+ pool.setAllocator(this);
+ pool.setDestructor(this);
+
+ assertFalse(pool.isDrained());
+
+ assertEquals(0, pool.getAllocatedSize());
+ for (int i = 0; i < SIZE; i++) {
+ array[i] = (Proxy) pool.reserve();
+ }
+ assertEquals(SIZE, pool.getAllocatedSize());
+
+ for (int i = 0; i < FREE; i++) {
+ pool.release((Testable) array[i]);
+ }
+ assertEquals(ALLOC, pool.getAllocatedSize());
+ assertEquals(FREE, pool.getFreeSize());
+
+ pool.drain();
+ assertEquals(0, pool.getFreeSize());
+ assertEquals(0, pool.getAllocatedSize());
+ assertTrue(pool.isDrained());
+
+ assertEquals(SIZE, destroyCount);
+ }
+
+ /**
+ * @see org.onap.ccsdk.sli.core.utils.pool.Destructor#destroy(java.io.Closeable, org.onap.ccsdk.sli.core.utils.pool.Pool)
+ */
+ @Override
+ public void destroy(Testable obj, Pool<Testable> pool) {
+ destroyCount++;
+ try {
+ obj.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @see org.onap.ccsdk.sli.core.utils.pool.Allocator#allocate(org.onap.ccsdk.sli.core.utils.pool.Pool)
+ */
+ @Override
+ public Testable allocate(Pool<Testable> pool) {
+ Testable e = new org.onap.ccsdk.sli.core.utils.pool.Element(index++);
+
+ return e;
+ }
+
+ @Test
+ public void testGetAndSetProperties() throws PoolSpecificationException
+ {
+ pool= new Pool<Testable>(3, 5);
+ pool.setProperty("key1", "value1");
+ assertEquals("value1", pool.getProperty("key1"));
+ }
+
+ @Test
+ public void testGetProperties() throws PoolSpecificationException
+ {
+ pool= new Pool<Testable>(3, 5);
+ assertTrue(pool.getProperties() instanceof Properties);
+ }
+}
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/Testable.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/Testable.java
new file mode 100644
index 000000000..95da40409
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/pool/Testable.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.ccsdk.sli.core.utils.pool;
+
+import java.io.Closeable;
+
+public interface Testable extends Closeable {
+
+ Integer getId();
+
+ Boolean isClosed();
+}
+