summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorruilin cai <ruilin.cai@huawei.com>2023-05-15 14:51:41 -0400
committerRuilin Cai <ruilin.cai@huawei.com>2023-06-16 20:49:53 +0000
commit4f9578356868d3b2d49cbef105fefdf7be74fd1f (patch)
treeae6ef369b059c60086e03e215579aa4a271c3501
parent276dede19944314ccfff76d55edd070115321c10 (diff)
[actn-interface-tools] Add restconf module. Create empty shell for global-control and yang-utils modules. Add copyrights and delete unessessary comments and unneeded resource files.
restconf module: This module is to send restful request to SDN by using restconf. It acts as a client to send restful requests to the SDN server. global-control module: This module controls the lifecycle and initiation of objects in other modules. yang-utils module: This module response for transferring between yang pojo and json. Also in this commit delete unneeded resource files, add copyrights to the maven pom files and delete some unnessessary comments. Change-Id: Idfc04649285bd6c5b67b1cc6c2115bf4bb267660 Signed-off-by: ruilin cai <ruilin.cai@huawei.com> Issue-ID: INT-2213 Signed-off-by: ruilin cai <ruilin.cai@huawei.com>
-rw-r--r--actn-interface-tools/global-control/pom.xml31
-rw-r--r--actn-interface-tools/pom.xml24
-rw-r--r--actn-interface-tools/restconf-client/api/pom.xml45
-rw-r--r--actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/DefaultPncInstance.java127
-rw-r--r--actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/PncInstance.java81
-rw-r--r--actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/RestConfSBController.java216
-rw-r--r--actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/RestconfNotificationEventListener.java36
-rw-r--r--actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/WebClientUtil.java61
-rw-r--r--actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/package-info.java24
-rw-r--r--actn-interface-tools/restconf-client/ctl/pom.xml81
-rw-r--r--actn-interface-tools/restconf-client/ctl/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/ctl/RestConfSBControllerImpl.java512
-rw-r--r--actn-interface-tools/restconf-client/ctl/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/ctl/package-info.java24
-rw-r--r--actn-interface-tools/restconf-client/pom.xml89
-rw-r--r--actn-interface-tools/yang-utils/pom.xml30
14 files changed, 1381 insertions, 0 deletions
diff --git a/actn-interface-tools/global-control/pom.xml b/actn-interface-tools/global-control/pom.xml
new file mode 100644
index 0000000..1c01ad8
--- /dev/null
+++ b/actn-interface-tools/global-control/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ Actn Interface Tools
+ ~ ================================================================================
+ ~ Copyright (C) 2022 Huawei Canada Limited.
+ ~ ================================================================================
+ ~ 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=========================================================
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.integration.ietf-actn-tools</groupId>
+ <artifactId>actn-interface-tools</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>global-control</artifactId>
+</project>
+
diff --git a/actn-interface-tools/pom.xml b/actn-interface-tools/pom.xml
index baa2400..b92341b 100644
--- a/actn-interface-tools/pom.xml
+++ b/actn-interface-tools/pom.xml
@@ -31,10 +31,14 @@
<modules>
<module>actn-model</module>
<module>actn-client</module>
+ <module>global-control</module>
+ <module>yang-utils</module>
+ <module>restconf-client</module>
</modules>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
+ <slf4j.version>1.7.21</slf4j.version>
</properties>
<dependencies>
<dependency>
@@ -49,12 +53,32 @@
<version>2.0.1</version>
<scope>compile</scope>
</dependency>
+
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<scope>provided</scope>
<version>1.9.12</version>
</dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.auto.service</groupId>
+ <artifactId>auto-service-annotations</artifactId>
+ <version>1.0</version>
+ <scope>compile</scope>
+ </dependency>
+
+
+
</dependencies>
</project> \ No newline at end of file
diff --git a/actn-interface-tools/restconf-client/api/pom.xml b/actn-interface-tools/restconf-client/api/pom.xml
new file mode 100644
index 0000000..49998cb
--- /dev/null
+++ b/actn-interface-tools/restconf-client/api/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ Actn Interface Tools
+ ~ ================================================================================
+ ~ Copyright (C) 2023 Huawei Canada Limited.
+ ~ ================================================================================
+ ~ 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=========================================================
+ -->
+
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.integration.ietf-actn-tools</groupId>
+ <artifactId>restconf-client</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <groupId>org.onap.integration.ietf-actn-tools</groupId>
+ <artifactId>restconf-client-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <!-- <packaging>bundle</packaging>-->
+ <packaging>jar</packaging>
+ <description>ONOS RESTCONF southbound plugin API</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.5</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/DefaultPncInstance.java b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/DefaultPncInstance.java
new file mode 100644
index 0000000..4bb8b66
--- /dev/null
+++ b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/DefaultPncInstance.java
@@ -0,0 +1,127 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Actn Interface Tools
+ * ================================================================================
+ * Copyright (C) 2023 Huawei Canada Limited.
+ * ================================================================================
+ * 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.integration.actninterfacetools.protocol.restconf;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+import org.apache.commons.lang3.StringUtils;
+import java.net.InetAddress;
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * Default implementation for Rest devices.
+ */
+public class DefaultPncInstance implements PncInstance {
+ private static final String REST = "rest";
+ private static final String COLON = ":";
+
+ private final UUID pncId;
+ private final InetAddress ip;
+ private final int port;
+ private final String username;
+ private final String password;
+ private String protocol;
+ private String url;
+
+ public DefaultPncInstance(InetAddress ip, int port, String name, String password,
+ String protocol, String url) {
+ this.pncId = UUID.randomUUID();
+ Preconditions.checkNotNull(ip, "IP address cannot be null");
+ Preconditions.checkArgument(port > 0, "Port address cannot be negative");
+ Preconditions.checkNotNull(protocol, "protocol address cannot be null");
+ this.ip = ip;
+ this.port = port;
+ this.username = name;
+ this.password = StringUtils.isEmpty(password) ? null : password;
+ this.protocol = protocol;
+ this.url = StringUtils.isEmpty(url) ? null : url;
+ }
+
+ @Override
+ public InetAddress ip() {
+ return this.ip;
+ }
+
+ @Override
+ public int port() {
+ return this.port;
+ }
+
+ @Override
+ public String username() {
+ return this.username;
+ }
+
+ @Override
+ public String password() {
+ return this.password;
+ }
+
+ @Override
+ public UUID pncId() {
+ return this.pncId;
+ }
+
+ @Override
+ public String protocol() {
+ return protocol;
+ }
+
+ @Override
+ public String url() {
+ return url;
+ }
+
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .omitNullValues()
+ .add("url", url)
+ .add("protocol", protocol)
+ .add("username", username)
+ .add("port", port)
+ .add("ip", ip)
+ .toString();
+
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof PncInstance)) {
+ return false;
+ }
+ PncInstance pncInstance = (PncInstance) obj;
+ return this.username.equals(pncInstance.username()) && this.ip.equals(pncInstance.ip()) &&
+ this.port == pncInstance.port();
+
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ip, port);
+ }
+
+}
diff --git a/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/PncInstance.java b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/PncInstance.java
new file mode 100644
index 0000000..a6726e8
--- /dev/null
+++ b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/PncInstance.java
@@ -0,0 +1,81 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Actn Interface Tools
+ * ================================================================================
+ * Copyright (C) 2023 Huawei Canada Limited.
+ * ================================================================================
+ * 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.integration.actninterfacetools.protocol.restconf;
+
+import java.net.InetAddress;
+import java.util.Optional;
+import java.util.UUID;
+
+/**
+ * Represents an abstraction of a Pnc.
+ */
+public interface PncInstance {
+ /**
+ * Returns the ip of the Pnc Service.
+ *
+ * @return ip
+ */
+ InetAddress ip();
+
+ /**
+ * Returns the port of the Pnc Service.
+ *
+ * @return port
+ */
+ int port();
+
+ /**
+ * Returns the username of the Pnc Service.
+ *
+ * @return username
+ */
+ String username();
+
+ /**
+ * Returns the password of the Pnc Service.
+ *
+ * @return password
+ */
+ String password();
+
+ /**
+ * Returns the pncId.
+ *
+ * @return pncId
+ */
+ UUID pncId();
+
+
+ /**
+ * Returns the protocol for the REST request, usually HTTP o HTTPS.
+ *
+ * @return protocol
+ */
+ String protocol();
+
+ /**
+ * Returns the url for the REST requests, to be used instead of IP and PORT.
+ *
+ * @return url
+ */
+ String url();
+
+}
diff --git a/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/RestConfSBController.java b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/RestConfSBController.java
new file mode 100644
index 0000000..86cfbc6
--- /dev/null
+++ b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/RestConfSBController.java
@@ -0,0 +1,216 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Actn Interface Tools
+ * ================================================================================
+ * Copyright (C) 2023 Huawei Canada Limited.
+ * ================================================================================
+ * 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.integration.actninterfacetools.protocol.restconf;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import javax.ws.rs.core.MediaType;
+import java.net.InetAddress;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Abstraction of a RESTCONF controller. Serves as a one-stop shop for obtaining
+ * RESTCONF southbound devices and (un)register listeners.
+ */
+public interface RestConfSBController {
+ /**
+ * Returns all the devices known to this controller.
+ *
+ * @return map of devices
+ */
+ Map<UUID, PncInstance> getPncInstances();
+
+ /**
+ * Returns a device by node identifier.
+ *
+ * @param deviceInfo node identifier
+ * @return RestSBDevice rest device
+ */
+ PncInstance getPncInstance(UUID deviceInfo);
+
+ /**
+ * Returns a device by Ip and Port.
+ *
+ * @param ip device ip
+ * @param port device port
+ * @return RestSBDevice rest device
+ */
+ PncInstance getPncInstance(InetAddress ip, int port);
+
+ /**
+ * Adds a device to the device map.
+ *
+ * @param pncInstance to be added
+ */
+ void addPncInstance(PncInstance pncInstance);
+
+ /**
+ * Removes the device from the devices map.
+ *
+ * @param pncId to be removed
+ */
+ void removeDevice(UUID pncId);
+ /**
+ * This method is to be called by whoever is interested to receive
+ * Notifications from a specific device. It does a REST GET request
+ * with specified parameters to the device, and calls the provided
+ * callBackListener upon receiving notifications to notify the requester
+ * about notifications.
+ *
+ * @param pncId pnc to make the request to
+ * @param request url of the request
+ * @param mediaType format to retrieve the content in
+ * @param callBackListener method to call when notifications arrives
+ */
+ void enableNotifications(UUID pncId, String request, String mediaType,
+ RestconfNotificationEventListener callBackListener);
+
+ /**
+ * Registers a listener for notification events that occur to restconf
+ * devices.
+ *
+ * @param pncId identifier of the pnc to which the listener is attached
+ * @param listener the listener to notify
+ */
+ void addNotificationListener(UUID pncId,
+ RestconfNotificationEventListener listener);
+
+ /**
+ * Unregisters the listener for the device.
+ *
+ * @param pncId identifier of the pnc for which the listener
+ * is to be removed
+ * @param listener listener to be removed
+ */
+ void removeNotificationListener(UUID pncId,
+ RestconfNotificationEventListener listener);
+
+ /**
+ * Returns true if a listener has been installed to listen to RESTCONF
+ * notifications sent from a particular device.
+ *
+ * @param pncId identifier of the pnc from which the notifications
+ * are generated
+ * @return true if listener is installed; false otherwise
+ */
+ boolean isNotificationEnabled(UUID pncId);
+
+ /**
+ * HTTP POST request with specified parameters to the pnc.
+ *
+ * @param pncId pnc to make the request to
+ * @param request url of the request
+ * @param payload payload of the request as an ObjectNode
+ * @param mediaType type of content in the payload i.e. application/json
+ * @return status Commonly used status codes defined by HTTP
+ */
+ int post(UUID pncId, String request, ObjectNode payload, MediaType mediaType);
+ /**
+ * HTTP POST request with specified parameters to the pnc.
+ *
+ * @param pncId pnc to make the request to
+ * @param request url of the request
+ * @param payload payload of the request as an ObjectNode
+ * @param mediaType type of content in the payload in the form of string i.e. "application/json"
+ * @return true if status defined by HTTP is OK, CREATED, ACCEPTED or PARTIAL-CONTEND, otherwise return false
+ */
+ boolean post(UUID pncId, String request, ObjectNode payload, String mediaType);
+
+ <T> T post(UUID pncId, String request, ObjectNode payload, String mediaType, Class<T> responseClass);
+
+ <T> T post(UUID pncId, String request, ObjectNode payload, MediaType mediaType, Class<T> responseClass);
+
+ /**
+ * HTTP PUT request with specified parameters to the device.
+ *
+ * @param pncId pnc to make the request to
+ * @param request resource path of the request
+ * @param payload payload of the request as an ObjectNode
+ * @param mediaType type of content in the payload i.e. application/json
+ * @return status Commonly used status codes defined by HTTP
+ */
+ int put(UUID pncId, String request, ObjectNode payload, MediaType mediaType);
+
+ /**
+ * HTTP PUT request with specified parameters to the pnc.
+ *
+ * @param pncId pnc to make the request to
+ * @param request url of the request
+ * @param payload payload of the request as an ObjectNode
+ * @param mediaType type of content in the payload in the form of string i.e. "application/json"
+ * @return true if status defined by HTTP is OK, CREATED, ACCEPTED or PARTIAL-CONTEND, otherwise return false
+ */
+ boolean put(UUID pncId, String request, ObjectNode payload, String mediaType);
+
+ /**
+ * HTTP PATCH request with specified parameters to the device.
+ *
+ * @param pncId pnc to make the request to
+ * @param request url of the request
+ * @param payload payload of the request as an ObjectNode
+ * @param mediaType format to retrieve the content in
+ * @return status Commonly used status codes defined by HTTP
+ */
+ int patch(UUID pncId, String request, ObjectNode payload, MediaType mediaType);
+
+ /**
+ * HTTP PATCH request with specified parameters to the pnc.
+ *
+ * @param pncId pnc to make the request to
+ * @param request url of the request
+ * @param payload payload of the request as an ObjectNode
+ * @param mediaType type of content in the payload i.e. application/json
+ * @return status Commonly used status codes defined by HTTP
+ */
+ boolean patch(UUID pncId, String request, ObjectNode payload, String mediaType);
+
+ /**
+ * HTTP DELETE request with specified parameters to the device.
+ *
+ * @param pncId pnc to make the request to
+ * @param request url of the request
+ * @param mediaType type of content in the payload i.e. application/json
+ * @return status Commonly used status codes defined by HTTP
+ */
+ int delete(UUID pncId, String request, MediaType mediaType);
+
+ /**
+ * HTTP DELETE request with specified parameters to the pnc.
+ *
+ * @param pncId pnc to make the request to
+ * @param request url of the request
+ * @param mediaType type of content in the payload i.e. application/json
+ * @return status Commonly used status codes defined by HTTP
+ */
+ boolean delete(UUID pncId, String request, String mediaType);
+
+ /**
+ *
+ * HTTP GET request with specified parameters to the device.
+ *
+ * @param pncId pnc to make the request to
+ * @param request url of the request
+ * @param mediaType format to retrieve the content in
+ * @return an ObjectNode of data from the reply.
+ */
+ ObjectNode get(UUID pncId, String request, String mediaType);
+
+}
diff --git a/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/RestconfNotificationEventListener.java b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/RestconfNotificationEventListener.java
new file mode 100644
index 0000000..70eb2d6
--- /dev/null
+++ b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/RestconfNotificationEventListener.java
@@ -0,0 +1,36 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Actn Interface Tools
+ * ================================================================================
+ * Copyright (C) 2023 Huawei Canada Limited.
+ * ================================================================================
+ * 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.integration.actninterfacetools.protocol.restconf;
+
+import java.util.UUID;
+
+/**
+ * Notifies providers about incoming RESTCONF notification events.
+ */
+public interface RestconfNotificationEventListener<T> {
+
+ /**
+ * Handles the notification event.
+ *
+ * @param pncId restconf device identifier
+ * @param event event payload
+ */
+ void handleNotificationEvent(UUID pncId, T event);
+}
diff --git a/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/WebClientUtil.java b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/WebClientUtil.java
new file mode 100644
index 0000000..066d4bd
--- /dev/null
+++ b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/WebClientUtil.java
@@ -0,0 +1,61 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Actn Interface Tools
+ * ================================================================================
+ * Copyright (C) 2023 Huawei Canada Limited.
+ * ================================================================================
+ * 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.integration.actninterfacetools.protocol.restconf;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class WebClientUtil {
+
+ protected static final Logger LOGGER = LoggerFactory.getLogger(WebClientUtil.class);
+
+ private WebClientUtil() {
+ }
+
+ public static String resetContentRange(String range) {
+ String rangeResult = "";
+ if (range != null) {
+ final Pattern pattern = Pattern.compile("\\d+\\-\\d+/\\S+");
+ final Matcher matcher = pattern.matcher(range);
+ if (matcher.find()) {
+ final String[] result = matcher.group(0).split("/");
+ if (result.length >= 2) {
+ final String[] ranges = result[0].split("\\D");
+ // 如果返回截止长度大于等于总长度-1,则认为结束
+ if (isContentEnd(ranges[1], result[1])) {
+ return "";
+ }
+ rangeResult = "bytes=" + (Integer.parseInt(ranges[1]) + 1) + "-"
+ + (result[1].equals("*") ? "" : result[1]);
+ }
+ }
+ }
+ return rangeResult;
+ }
+
+ private static boolean isContentEnd(String end, String total) {
+ return total.matches("[0-9]*") && Integer.parseInt(end) >= Integer.parseInt(total) - 1;
+ }
+
+}
diff --git a/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/package-info.java b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/package-info.java
new file mode 100644
index 0000000..6551498
--- /dev/null
+++ b/actn-interface-tools/restconf-client/api/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Actn Interface Tools
+ * ================================================================================
+ * Copyright (C) 2023 Huawei Canada Limited.
+ * ================================================================================
+ * 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=========================================================
+ */
+
+/**
+ * RESTCONF southbound protocols libraries.
+ */
+package org.onap.integration.actninterfacetools.protocol.restconf;
diff --git a/actn-interface-tools/restconf-client/ctl/pom.xml b/actn-interface-tools/restconf-client/ctl/pom.xml
new file mode 100644
index 0000000..6326889
--- /dev/null
+++ b/actn-interface-tools/restconf-client/ctl/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ Actn Interface Tools
+ ~ ================================================================================
+ ~ Copyright (C) 2023 Huawei Canada Limited.
+ ~ ================================================================================
+ ~ 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=========================================================
+ -->
+
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.integration.ietf-actn-tools</groupId>
+ <artifactId>restconf-client</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>restconf-client-ctl</artifactId>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.integration.ietf-actn-tools</groupId>
+ <artifactId>restconf-client-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ <version>2.3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ <scope>provided</scope>
+ <version>1.9.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ <version>5.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>2.9</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient-osgi</artifactId>
+ <version>4.5.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore-osgi</artifactId>
+ <version>4.4.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/actn-interface-tools/restconf-client/ctl/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/ctl/RestConfSBControllerImpl.java b/actn-interface-tools/restconf-client/ctl/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/ctl/RestConfSBControllerImpl.java
new file mode 100644
index 0000000..71f8797
--- /dev/null
+++ b/actn-interface-tools/restconf-client/ctl/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/ctl/RestConfSBControllerImpl.java
@@ -0,0 +1,512 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Actn Interface Tools
+ * ================================================================================
+ * Copyright (C) 2023 Huawei Canada Limited.
+ * ================================================================================
+ * 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.integration.actninterfacetools.protocol.restconf.ctl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableMap;
+import org.apache.http.client.methods.HttpPatch;
+import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.glassfish.jersey.client.ChunkedInput;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.onap.integration.actninterfacetools.protocol.restconf.PncInstance;
+import org.onap.integration.actninterfacetools.protocol.restconf.RestConfSBController;
+import org.onap.integration.actninterfacetools.protocol.restconf.RestconfNotificationEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * The implementation of RestConfSBController.
+ */
+
+public class RestConfSBControllerImpl implements RestConfSBController {
+ private static volatile RestConfSBControllerImpl restConfClientInstance = null;
+ private static final int STATUS_OK = Response.Status.OK.getStatusCode();
+ private static final int STATUS_CREATED = Response.Status.CREATED.getStatusCode();
+ private static final int STATUS_ACCEPTED = Response.Status.ACCEPTED.getStatusCode();
+ private static final int PARTIAL_CONTENT = Response.Status.PARTIAL_CONTENT.getStatusCode();
+ protected static final String DOUBLESLASH = "/";
+ protected static final String COLON = ":";
+ private static final String XML = "xml";
+ private static final String JSON = "json";
+ private static final String HTTPS = "https";
+ private static final String AUTHORIZATION_PROPERTY = "authorization";
+ private static final String BASIC_AUTH_PREFIX = "Basic ";
+ private static final Logger log = LoggerFactory
+ .getLogger(RestConfSBControllerImpl.class);
+
+ // TODO: for the Ibis release when both RESTCONF server and RESTCONF client
+ // fully support root resource discovery, ROOT_RESOURCE constant will be
+ // removed and rather the value would get discovered dynamically.
+ private static final String ROOT_RESOURCE = "/restconf";
+
+ private static final String RESOURCE_PATH_PREFIX = "/data/";
+ private static final String NOTIFICATION_PATH_PREFIX = "/streams/";
+
+ private Map<UUID, Set<RestconfNotificationEventListener>>
+ restconfNotificationListenerMap = new ConcurrentHashMap<>();
+ private Map<UUID, GetChunksRunnable> runnableTable = new ConcurrentHashMap<>();
+ private final Map<UUID, PncInstance> pncMap = new ConcurrentHashMap<>();
+ private final Map<UUID, Client> clientMap = new ConcurrentHashMap<>();
+
+ ExecutorService executor = Executors.newCachedThreadPool();
+
+ private RestConfSBControllerImpl(){
+
+ }
+ public static RestConfSBControllerImpl getRestConfClient(){
+ if(restConfClientInstance != null){
+ return restConfClientInstance;
+ }
+ synchronized (RestConfSBControllerImpl.class) {
+ if(restConfClientInstance == null){
+ restConfClientInstance = new RestConfSBControllerImpl();
+
+ }
+ return restConfClientInstance;
+ }
+ }
+
+ public void activate() {
+ log.info("RESTCONF SBI Started");
+ }
+
+ public void deactivate() {
+ log.info("RESTCONF SBI Stopped");
+ executor.shutdown();
+ this.clientMap.clear();
+ this.pncMap.clear();
+ }
+
+ public Map<UUID, PncInstance> getPncInstances() {
+ log.trace("RESTCONF SBI::getDevices");
+ return ImmutableMap.copyOf(pncMap);
+ }
+
+ public PncInstance getPncInstance(UUID pncInfo) {
+ log.trace("RESTCONF SBI::getDevice with deviceId");
+ return pncMap.get(pncInfo);
+ }
+
+ public PncInstance getPncInstance(InetAddress ip, int port) {
+ log.trace("RESTCONF SBI::getDevice with ip and port");
+ return pncMap.values().stream().filter(v -> v.ip().equals(ip) && v.port() == port).findFirst().get();
+ }
+
+ public void addPncInstance(PncInstance pncInstance) {
+ log.trace("RESTCONF SBI::addDevice");
+ if (!pncMap.containsKey(pncInstance.pncId())) {
+ Client client = ignoreSslClient();
+ if (pncInstance.username() != null) {
+ String username = pncInstance.username();
+ String password = pncInstance.password() == null ? "" : pncInstance.password();
+ client.register(HttpAuthenticationFeature.basic(username, password));
+ }
+ clientMap.put(pncInstance.pncId(), client);
+ pncMap.put(pncInstance.pncId(), pncInstance);
+ } else {
+ log.warn("Trying to add a device that is already existing {}", pncInstance.pncId());
+ }
+ }
+ private Client ignoreSslClient() {
+ SSLContext sslcontext = null;
+
+ try {
+ sslcontext = SSLContext.getInstance("TLS");
+ sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
+ public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+ }
+
+ public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ }}, new java.security.SecureRandom());
+ } catch (NoSuchAlgorithmException | KeyManagementException e) {
+ e.printStackTrace();
+ }
+
+ return ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier((s1, s2) -> true).build();
+ }
+
+ public void removeDevice(UUID pncId) {
+ log.trace("RESTCONF SBI::removeDevice");
+ clientMap.remove(pncId);
+ pncMap.remove(pncId);
+ }
+ @Override
+ public boolean post(UUID pncId, String request, ObjectNode payload,
+ String mediaType) {
+ request = discoverRootResource(pncId) + RESOURCE_PATH_PREFIX
+ + request;
+ return checkStatusCode(post(pncId, request, payload, typeOfMediaType(mediaType)));
+ }
+ private MediaType typeOfMediaType(String type) {
+ switch (type) {
+ case XML:
+ return MediaType.APPLICATION_XML_TYPE;
+ case JSON:
+ return MediaType.APPLICATION_JSON_TYPE;
+ case MediaType.WILDCARD:
+ return MediaType.WILDCARD_TYPE;
+ default:
+ throw new IllegalArgumentException("Unsupported media type " + type);
+
+ }
+ }
+ private boolean checkStatusCode(int statusCode) {
+ if (statusCode == STATUS_OK || statusCode == STATUS_CREATED || statusCode == STATUS_ACCEPTED) {
+ return true;
+ } else {
+ log.error("Failed request, HTTP error code : " + statusCode);
+ return false;
+ }
+ }
+ @Override
+ public int post(UUID pndId, String request, ObjectNode payload, MediaType mediaType) {
+ Response response = getResponse(pndId, request, payload, mediaType);
+ if (response == null) {
+ return Response.Status.NO_CONTENT.getStatusCode();
+ }
+ return response.getStatus();
+ }
+ private Response getResponse(UUID pncId, String request, ObjectNode payload, MediaType mediaType) {
+
+ WebTarget wt = getWebTarget(pncId, request);
+
+ Response response = null;
+ if (payload != null) {
+ try {
+ response = wt.request(mediaType)
+ .post(Entity.entity(payload.toString(), mediaType));
+ } catch (Exception e) {
+ log.error("Cannot do POST {} request on device {} because can't read payload", request, pncId);
+ }
+ } else {
+ response = wt.request(mediaType).post(Entity.entity(null, mediaType));
+ }
+ return response;
+ }
+ protected WebTarget getWebTarget(UUID pncId, String request) {
+ log.info("Sending request to URL {} ", getUrlString(pncId, request));
+ return clientMap.get(pncId).target(getUrlString(pncId, request));
+ }
+ protected String getUrlString(UUID pncId, String request) {
+ PncInstance pncInstance = pncMap.get(pncId);
+ if (pncInstance == null) {
+ log.warn("restSbDevice cannot be NULL!");
+ return "";
+ }
+ if (pncInstance.url() != null) {
+ return pncInstance.protocol() + COLON + DOUBLESLASH + pncInstance.url() + request;
+ } else {
+ return pncInstance.protocol() + COLON + DOUBLESLASH + pncInstance.ip().toString()
+ + COLON + pncInstance.port() + request;
+ }
+ }
+ @Override
+ public <T> T post(UUID pncId, String request, ObjectNode payload,
+ String mediaType, Class<T> responseClass) {
+ request = discoverRootResource(pncId) + RESOURCE_PATH_PREFIX
+ + request;
+ return post(pncId, request, payload, typeOfMediaType(mediaType), responseClass);
+ }
+ @Override
+ public <T> T post(UUID device, String request, ObjectNode payload, MediaType mediaType,
+ Class<T> responseClass) {
+ Response response = getResponse(device, request, payload, mediaType);
+ if (response != null && response.hasEntity()) {
+ return responseClass == Response.class ? (T) response : response.readEntity(responseClass);
+ }
+ log.error("Response from device {} for request {} contains no entity", device, request);
+ return null;
+ }
+ @Override
+ public boolean put(UUID pncId, String request, ObjectNode payload,
+ String mediaType) {
+ request = discoverRootResource(pncId) + RESOURCE_PATH_PREFIX
+ + request;
+ return checkStatusCode(put(pncId, request, payload, typeOfMediaType(mediaType)));
+ }
+ @Override
+ public int put(UUID pncId, String request, ObjectNode payload, MediaType mediaType) {
+
+ WebTarget wt = getWebTarget(pncId, request);
+
+ Response response = null;
+ if (payload != null) {
+ try {
+ response = wt.request(mediaType).put(Entity.entity(payload.toString(), mediaType));
+ } catch (Exception e) {
+ log.error("Cannot do PUT {} request on device {} because can't read payload", request, pncId);
+ }
+ } else {
+ response = wt.request(mediaType).put(Entity.entity(null, mediaType));
+ }
+
+ if (response == null) {
+ return Response.Status.NO_CONTENT.getStatusCode();
+ }
+ return response.getStatus();
+ }
+ @Override
+ public ObjectNode get(UUID pncId, String request, String mediaType) {
+ request = discoverRootResource(pncId) + RESOURCE_PATH_PREFIX
+ + request;
+ return get(pncId, request, typeOfMediaType(mediaType));
+ }
+ public ObjectNode get(UUID pncId, String request, MediaType mediaType) {
+ WebTarget wt = getWebTarget(pncId, request);
+
+ Response s = wt.request(mediaType).get();
+
+ if (checkReply(s)) {
+ try {
+ String json = s.readEntity((String.class));
+ return new ObjectMapper().readTree(json).deepCopy();
+ } catch (Exception ex) {
+ log.error("ERROR: ", ex);
+ }
+ }
+
+ return null;
+ }
+ private boolean checkReply(Response response) {
+ if (response != null) {
+ boolean statusCode = checkStatusCode(response.getStatus());
+ if (!statusCode && response.hasEntity()) {
+ log.error("Failed request, HTTP error msg : " + response.readEntity(String.class));
+ }
+ return statusCode;
+ }
+ log.error("Null reply from device");
+ return false;
+ }
+ @Override
+ public boolean patch(UUID pncId, String request, ObjectNode payload,
+ String mediaType) {
+ request = discoverRootResource(pncId) + RESOURCE_PATH_PREFIX
+ + request;
+ return checkStatusCode(patch(pncId, request, payload, typeOfMediaType(mediaType)));
+ }
+ @Override
+ public int patch(UUID pncId, String request, ObjectNode payload, MediaType mediaType) {
+
+ try {
+ log.debug("Url request {} ", getUrlString(pncId, request));
+ HttpPatch httprequest = new HttpPatch(getUrlString(pncId, request));
+ if (pncMap.get(pncId).username() != null) {
+ String pwd = pncMap.get(pncId).password() == null ? "" : COLON + pncMap.get(pncId).password();
+ String userPassword = pncMap.get(pncId).username() + pwd;
+ String base64string = Base64.getEncoder().encodeToString(userPassword.getBytes(StandardCharsets.UTF_8));
+ httprequest.addHeader(AUTHORIZATION_PROPERTY, BASIC_AUTH_PREFIX + base64string);
+ }
+ if (payload != null) {
+ StringEntity input = new StringEntity(payload.toString());
+ input.setContentType(mediaType.toString());
+ httprequest.setEntity(input);
+ }
+ CloseableHttpClient httpClient;
+ if (pncMap.containsKey(pncId) && pncMap.get(pncId).protocol().equals(HTTPS)) {
+ httpClient = getApacheSslBypassClient();
+ } else {
+ httpClient = HttpClients.createDefault();
+ }
+ return httpClient.execute(httprequest).getStatusLine().getStatusCode();
+ } catch (IOException | NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
+ log.error("Cannot do PATCH {} request on device {}", request, pncId, e);
+ }
+ return Response.Status.BAD_REQUEST.getStatusCode();
+ }
+ private CloseableHttpClient getApacheSslBypassClient() throws NoSuchAlgorithmException,
+ KeyManagementException, KeyStoreException {
+ return HttpClients.custom().
+ setHostnameVerifier(new AllowAllHostnameVerifier()).
+ setSslcontext(new SSLContextBuilder()
+ .loadTrustMaterial(null, (arg0, arg1) -> true)
+ .build()).build();
+ }
+ @Override
+ public boolean delete(UUID pncId, String request,
+ String mediaType) {
+ request = discoverRootResource(pncId) + RESOURCE_PATH_PREFIX
+ + request;
+ return checkStatusCode(delete(pncId, request, typeOfMediaType(mediaType)));
+ }
+ @Override
+ public int delete(UUID pncId, String request, MediaType mediaType) {
+
+ WebTarget wt = getWebTarget(pncId, request);
+
+ Response response = wt.request(mediaType).delete();
+
+ return response.getStatus();
+ }
+ @Override
+ public void enableNotifications(UUID pncId, String request,
+ String mediaType,
+ RestconfNotificationEventListener listener) {
+
+ if (isNotificationEnabled(pncId)) {
+ log.warn("enableNotifications: already enabled on device: {}", pncId);
+ return;
+ }
+
+ request = discoverRootResource(pncId) + NOTIFICATION_PATH_PREFIX
+ + request;
+
+ addNotificationListener(pncId, listener);
+
+ GetChunksRunnable runnable = new GetChunksRunnable(request, mediaType,
+ pncId);
+ runnableTable.put(pncId, runnable);
+ executor.execute(runnable);
+ }
+
+ public void stopNotifications(UUID pncId) {
+ runnableTable.get(pncId).terminate();
+ runnableTable.remove(pncId);
+ restconfNotificationListenerMap.remove(pncId);
+ log.debug("Stop sending notifications for device URI: " + pncId.toString());
+
+ }
+
+ public class GetChunksRunnable implements Runnable {
+ private String request;
+ private String mediaType;
+ private UUID pnc;
+
+ private volatile boolean running = true;
+
+ public void terminate() {
+ running = false;
+ }
+
+ /**
+ * @param request request
+ * @param mediaType media type
+ * @param pncId PNC identifier
+ */
+ public GetChunksRunnable(String request, String mediaType,
+ UUID pncId) {
+ this.request = request;
+ this.mediaType = mediaType;
+ this.pnc = pncId;
+ }
+
+ @Override
+ public void run() {
+ WebTarget wt = getWebTarget(pnc, request);
+ Response clientResp = wt.request(mediaType).get();
+ Set<RestconfNotificationEventListener> listeners =
+ restconfNotificationListenerMap.get(pnc);
+ final ChunkedInput<String> chunkedInput = (ChunkedInput<String>) clientResp
+ .readEntity(new GenericType<ChunkedInput<String>>() {
+ });
+
+ String chunk;
+ // Note that the read() is a blocking operation and the invoking
+ // thread is blocked until a new chunk comes. Jersey implementation
+ // of this IO operation is in a way that it does not respond to
+ // interrupts.
+ while (running) {
+ chunk = chunkedInput.read();
+ if (chunk != null) {
+ if (running) {
+ for (RestconfNotificationEventListener listener : listeners) {
+ listener.handleNotificationEvent(pnc, chunk);
+ }
+ } else {
+ log.trace("the requesting client is no more interested "
+ + "to receive such notifications.");
+ }
+ } else {
+ log.trace("The received notification chunk is null. do not continue any more.");
+ break;
+ }
+ }
+ log.trace("out of while loop -- end of run");
+ }
+ }
+
+ public String discoverRootResource(UUID pncId) {
+ // FIXME: send a GET command to the device to discover the root resource.
+ // The plan to fix this is for the Ibis release when the RESTCONF server and
+ // the RESTCONF client both support root resource discovery.
+ return ROOT_RESOURCE;
+ }
+
+ @Override
+ public void addNotificationListener(UUID pncId,
+ RestconfNotificationEventListener listener) {
+ Set<RestconfNotificationEventListener> listeners =
+ restconfNotificationListenerMap.get(pncId);
+ if (listeners == null) {
+ listeners = new HashSet<>();
+ }
+
+ listeners.add(listener);
+
+ this.restconfNotificationListenerMap.put(pncId, listeners);
+ }
+
+ @Override
+ public void removeNotificationListener(UUID pncId,
+ RestconfNotificationEventListener listener) {
+ Set<RestconfNotificationEventListener> listeners =
+ restconfNotificationListenerMap.get(pncId);
+ if (listeners != null) {
+ listeners.remove(listener);
+ }
+ }
+
+ public boolean isNotificationEnabled(UUID pncId) {
+ return runnableTable.containsKey(pncId);
+ }
+}
diff --git a/actn-interface-tools/restconf-client/ctl/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/ctl/package-info.java b/actn-interface-tools/restconf-client/ctl/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/ctl/package-info.java
new file mode 100644
index 0000000..a672161
--- /dev/null
+++ b/actn-interface-tools/restconf-client/ctl/src/main/java/org/onap/integration/actninterfacetools/protocol/restconf/ctl/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Actn Interface Tools
+ * ================================================================================
+ * Copyright (C) 2023 Huawei Canada Limited.
+ * ================================================================================
+ * 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=========================================================
+ */
+
+/**
+ * RESTCONF southbound protocol implementation.
+ */
+package org.onap.integration.actninterfacetools.protocol.restconf.ctl;
diff --git a/actn-interface-tools/restconf-client/pom.xml b/actn-interface-tools/restconf-client/pom.xml
new file mode 100644
index 0000000..f115180
--- /dev/null
+++ b/actn-interface-tools/restconf-client/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ Actn Interface Tools
+ ~ ================================================================================
+ ~ Copyright (C) 2023 Huawei Canada Limited.
+ ~ ================================================================================
+ ~ 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=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>actn-interface-tools</artifactId>
+ <groupId>org.onap.integration.ietf-actn-tools</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.onap.integration.ietf-actn-tools</groupId>
+ <artifactId>restconf-client</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ <scope>provided</scope>
+ <version>1.9.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ <version>5.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.8.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>2.9</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ <version>2.3.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient-osgi</artifactId>
+ <version>4.5.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore-osgi</artifactId>
+ <version>4.4.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+ </dependencies>
+ <modules>
+ <module>api</module>
+ <module>ctl</module>
+ </modules>
+ <description>RESTCONF Client Module</description>
+</project>
diff --git a/actn-interface-tools/yang-utils/pom.xml b/actn-interface-tools/yang-utils/pom.xml
new file mode 100644
index 0000000..6fc3a7c
--- /dev/null
+++ b/actn-interface-tools/yang-utils/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ Actn Interface Tools
+ ~ ================================================================================
+ ~ Copyright (C) 2022 Huawei Canada Limited.
+ ~ ================================================================================
+ ~ 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=========================================================
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.integration.ietf-actn-tools</groupId>
+ <artifactId>actn-interface-tools</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>yang-utils</artifactId>
+</project>