RESTCONF Server outline
Change-Id: Id93a647b35b24c47f2828763a799b56a50113faf
diff --git a/protocols/restconf/server/BUCK b/protocols/restconf/server/BUCK
new file mode 100644
index 0000000..8b4f0d2
--- /dev/null
+++ b/protocols/restconf/server/BUCK
@@ -0,0 +1,12 @@
+BUNDLES = [
+ '//protocols/restconf/server/api:onos-protocols-restconf-server-api',
+ '//protocols/restconf/server/restconfmgr:onos-protocols-restconf-server-restconfmgr',
+ '//protocols/restconf/server/rpp:onos-protocols-restconf-server-rpp',
+]
+
+onos_app (
+ title = 'RESTCONF Server Module',
+ category = 'Utility',
+ url = 'http://onosproject.org',
+ included_bundles = BUNDLES,
+)
diff --git a/protocols/restconf/server/api/BUCK b/protocols/restconf/server/api/BUCK
new file mode 100644
index 0000000..97d99aa
--- /dev/null
+++ b/protocols/restconf/server/api/BUCK
@@ -0,0 +1,10 @@
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+ '//lib:jersey-client',
+ '//lib:javax.ws.rs-api',
+ '//lib:jersey-server',
+]
+
+osgi_jar_with_tests (
+ deps = COMPILE_DEPS,
+)
diff --git a/protocols/restconf/server/api/pom.xml b/protocols/restconf/server/api/pom.xml
new file mode 100644
index 0000000..cee0c87
--- /dev/null
+++ b/protocols/restconf/server/api/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ 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.
+ -->
+<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>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-restconf-server</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-restconf-server-api</artifactId>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-serializers</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
+
diff --git a/protocols/restconf/server/api/src/main/java/org/onosproject/protocol/restconf/server/api/RestconfException.java b/protocols/restconf/server/api/src/main/java/org/onosproject/protocol/restconf/server/api/RestconfException.java
new file mode 100644
index 0000000..e6b572c
--- /dev/null
+++ b/protocols/restconf/server/api/src/main/java/org/onosproject/protocol/restconf/server/api/RestconfException.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.
+ */
+package org.onosproject.protocol.restconf.server.api;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+import static javax.ws.rs.core.Response.Status;
+
+/**
+ * Exceptions raised during RESTCONF operations. This class extends
+ * WebApplicationException. The design intention is to create a place holder
+ * for RESTCONF specific errors and to be able to add more functions as the
+ * subsystem grows.
+ */
+public class RestconfException extends WebApplicationException {
+
+ // This is a randomly generated value. A WebApplicationException class is required to define it.
+ private static final long SERIAL_VERSION_UID = 3275970397584007046L;
+
+ /**
+ * Constructs a new RESTCONF server error exception. The caller raising this
+ * exception may pass in a HTTP error status code and an error message. The
+ * error code will be displayed to the RESTCONF client as part of the
+ * response from the RESTCONF server. The error message is a string which
+ * may be saved in a log file and may be later retrieved by the
+ * getMessage() method.
+ *
+ * @param message the detailed error message
+ * @param status HTTP error status
+ * @throws IllegalArgumentException in case the status code is null or is not from
+ * javax.ws.rs.core.Response.Status.Family
+ * status code family
+ */
+ public RestconfException(String message, Status status) {
+ super(message, null, Response.status(status).build());
+ }
+
+ /**
+ * Constructs a new RESTCONF server error exception. The caller raising
+ * this exception may pass in the numerical value of a HTTP error
+ * status code, The error code will be displayed to the RESTCONF client
+ * as a response from the RESTCONF server.
+ *
+ * @param status HTTP error status
+ * @throws IllegalArgumentException in case the status code is not a valid
+ * HTTP status code or if it is not from the
+ * javax.ws.rs.core.Response.Status.Family
+ * status code family
+ */
+ public RestconfException(int status) {
+ super((Throwable) null, Response.status(status).build());
+ }
+}
diff --git a/protocols/restconf/server/api/src/main/java/org/onosproject/protocol/restconf/server/api/RestconfService.java b/protocols/restconf/server/api/src/main/java/org/onosproject/protocol/restconf/server/api/RestconfService.java
new file mode 100644
index 0000000..6fea21d
--- /dev/null
+++ b/protocols/restconf/server/api/src/main/java/org/onosproject/protocol/restconf/server/api/RestconfService.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.
+ */
+package org.onosproject.protocol.restconf.server.api;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.glassfish.jersey.server.ChunkedOutput;
+
+/**
+ * Abstraction of RESTCONF Server functionality according to the
+ * RESTCONF RFC (no official RFC number yet).
+ */
+public interface RestconfService {
+ /**
+ * Processes a GET request against a data resource. The
+ * target data resource is identified by its URI.
+ *
+ * @param uri URI of the target data resource
+ * @return JSON representation of the data resource
+ * @throws RestconfException if the GET operation cannot be fulfilled due
+ * reasons such as the nonexistence of the target
+ * resource. The proper HTTP error status code is
+ * enclosed in the exception, so that the caller
+ * may return it to the RESTCONF client
+ */
+ ObjectNode runGetOperationOnDataResource(String uri) throws RestconfException;
+
+ /**
+ * Processes a POST request against a data resource. The location of
+ * the target resource is passed in as a URI. And the resource's
+ * content is passed in as a JSON ObjectNode.
+ *
+ * @param uri URI of the data resource to be created
+ * @param rootNode JSON representation of the data resource
+ * @throws RestconfException if the POST operation cannot be fulfilled due
+ * reasons such as wrong URI or syntax error
+ * in JSON payload. The proper HTTP error status
+ * code is enclosed in the exception
+ */
+ void runPostOperationOnDataResource(String uri, ObjectNode rootNode) throws RestconfException;
+
+ /**
+ * Processes a PUT request against a data resource. The location of
+ * the target resource is passed in as a URI. And the resource's
+ * content is passed in as a JSON ObjectNode.
+ *
+ * @param uri URI of the data resource to be created or updated
+ * @param rootNode JSON representation of the data resource
+ * @throws RestconfException if the PUT operation cannot be fulfilled due
+ * reasons such as wrong URI or syntax error
+ * in JSON payload. The proper HTTP error status
+ * code is enclosed in the exception
+ */
+ void runPutOperationOnDataResource(String uri, ObjectNode rootNode) throws RestconfException;
+
+ /**
+ * Processes the DELETE operation against a data resource. The target
+ * data resource is identified by its URI.
+ *
+ * @param uri URI of the data resource to be deleted
+ * @throws RestconfException if the DELETE operation cannot be fulfilled due
+ * reasons such as the nonexistence of the target
+ * resource. The proper HTTP error status code is
+ * enclosed in the exception
+ */
+ void runDeleteOperationOnDataResource(String uri) throws RestconfException;
+
+ /**
+ * Retrieves the RESTCONF Root directory.
+ *
+ * @return the RESTCONF Root directory
+ */
+ String getRestconfRootPath();
+
+ /**
+ * Handles an Event Stream subscription request. This function creates
+ * a worker thread to listen to events and writes to a ChunkedOutput,
+ * which is passed in from the caller. (The worker thread blocks if
+ * no events arrive.) The ChuckedOutput is a pipe to which this
+ * function acts as the writer and the caller the reader.
+ *
+ * @param streamId ID of the RESTCONF stream to subscribe
+ * @param output A string data stream
+ * @throws RestconfException if the Event Stream cannot be subscribed due to
+ * reasons such as the nonexistence of the target
+ * stream or unable to allocate any free worker
+ * thread to handle the request
+ */
+ void subscribeEventStream(String streamId, ChunkedOutput<String> output) throws RestconfException;
+}
diff --git a/protocols/restconf/server/api/src/main/java/org/onosproject/protocol/restconf/server/api/package-info.java b/protocols/restconf/server/api/src/main/java/org/onosproject/protocol/restconf/server/api/package-info.java
new file mode 100644
index 0000000..e0bb150
--- /dev/null
+++ b/protocols/restconf/server/api/src/main/java/org/onosproject/protocol/restconf/server/api/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.
+ */
+
+/**
+ * RESTCONF Server Public Interface. All public interfaces/APIs that might be used by
+ * external applications should be packaged here.
+ */
+package org.onosproject.protocol.restconf.server.api;
diff --git a/protocols/restconf/server/app/app.xml b/protocols/restconf/server/app/app.xml
new file mode 100644
index 0000000..1e8723e
--- /dev/null
+++ b/protocols/restconf/server/app/app.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ 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.
+ -->
+<app name="org.onosproject.protocols.restconfserver" origin="ON.Lab" version="${project.version}"
+ category="Utility" url="http://onosproject.org" title="RESTCONF Service Module App"
+ featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
+ features="${project.artifactId}" >
+ <description>${project.description}</description>
+ <artifact>mvn:${project.groupId}/onos-restconf-server-api/${project.version}</artifact>
+ <artifact>mvn:${project.groupId}/onos-restconf-server-restconfmanager/${project.version}</artifact>
+ <artifact>mvn:${project.groupId}/onos-restconf-server-rpp/${project.version}</artifact>
+</app>
diff --git a/protocols/restconf/server/app/features.xml b/protocols/restconf/server/app/features.xml
new file mode 100644
index 0000000..b7bcce4
--- /dev/null
+++ b/protocols/restconf/server/app/features.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ 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.
+ -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+ <feature name="${project.artifactId}" version="${project.version}"
+ description="${project.description}">
+ <feature>onos-api</feature>
+ <bundle>mvn:${project.groupId}/onos-restconf-server-api/${project.version}</bundle>
+ <bundle>mvn:${project.groupId}/onos-restconf-server-restconfmanager/${project.version}</bundle>
+ <bundle>mvn:${project.groupId}/onos-restconf-server-rpp/${project.version}</bundle>
+ </feature>
+</features>
diff --git a/protocols/restconf/server/app/pom.xml b/protocols/restconf/server/app/pom.xml
new file mode 100644
index 0000000..0875b99
--- /dev/null
+++ b/protocols/restconf/server/app/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ 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.
+ -->
+<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>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-restconf-server</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-restconf-server-app</artifactId>
+ <packaging>pom</packaging>
+
+ <properties>
+ <onos.app.readme>RESTCONF Server Module main Application.</onos.app.readme>
+ </properties>
+
+ <description>RESTCONF Service Module main Application</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-restconf-server-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-restconf-server-restconfmanager</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-restconf-server-rpp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/protocols/restconf/server/pom.xml b/protocols/restconf/server/pom.xml
new file mode 100644
index 0000000..6ef2700
--- /dev/null
+++ b/protocols/restconf/server/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ 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.
+ -->
+<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>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-restconf</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-restconf-server</artifactId>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>api</module>
+ <module>restconfmgr</module>
+ <module>rpp</module>
+ <module>app</module>
+ </modules>
+
+ <description>RESTCONF Server Module</description>
+</project>
diff --git a/protocols/restconf/server/restconfmgr/BUCK b/protocols/restconf/server/restconfmgr/BUCK
new file mode 100644
index 0000000..100f922
--- /dev/null
+++ b/protocols/restconf/server/restconfmgr/BUCK
@@ -0,0 +1,13 @@
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+ '//lib:jersey-client',
+ '//lib:jersey-server',
+ '//lib:javax.ws.rs-api',
+ '//utils/rest:onlab-rest',
+ '//core/store/serializers:onos-core-serializers',
+ '//protocols/restconf/server/api:onos-protocols-restconf-server-api',
+]
+
+osgi_jar_with_tests (
+ deps = COMPILE_DEPS,
+)
diff --git a/protocols/restconf/server/restconfmgr/pom.xml b/protocols/restconf/server/restconfmgr/pom.xml
new file mode 100644
index 0000000..4c8b8c5
--- /dev/null
+++ b/protocols/restconf/server/restconfmgr/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ 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.
+ -->
+<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.onosproject</groupId>
+ <artifactId>onos-restconf-server</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-restconf-server-restconfmanager</artifactId>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-restconf-server-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-rest</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-rest</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-misc</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/protocols/restconf/server/restconfmgr/src/main/java/org/onosproject/protocol/restconf/server/restconfmanager/RestconfManager.java b/protocols/restconf/server/restconfmgr/src/main/java/org/onosproject/protocol/restconf/server/restconfmanager/RestconfManager.java
new file mode 100644
index 0000000..ee8506f
--- /dev/null
+++ b/protocols/restconf/server/restconfmgr/src/main/java/org/onosproject/protocol/restconf/server/restconfmanager/RestconfManager.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.
+ */
+package org.onosproject.protocol.restconf.server.restconfmanager;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.glassfish.jersey.server.ChunkedOutput;
+import org.onosproject.event.ListenerTracker;
+import org.onosproject.protocol.restconf.server.api.RestconfException;
+import org.onosproject.protocol.restconf.server.api.RestconfService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/*
+ * Skeletal ONOS RESTCONF Server application. The RESTCONF Manager
+ * implements the main logic of the RESTCONF Server.
+ *
+ * The design of the RESTCONF subsystem contains 2 major bundles:
+ *
+ * 1. RESTCONF Protocol Proxy (RPP). This bundle is implemented as a JAX-RS application.
+ * It acts as the frond-end of the the RESTCONF server. It handles
+ * HTTP requests that are sent to the RESTCONF Root Path. It then calls the RESTCONF Manager
+ * to process the requests.
+ *
+ * 2. RESTCONF Manager. This is the back-end. It provides the main logic of the RESTCONF server.
+ * It calls the YMS (YANG Management System) to operate on the YANG data objects.
+ */
+
+/**
+ * Implementation of the RestconfService interface. The class is designed
+ * as a Apache Flex component. Note that to avoid unnecessary
+ * activation, the @Component annotation's immediate parameter is set to false.
+ * So the component is not activated until a RESTCONF request is received by
+ * the RESTCONF Protocol Proxy (RPP) module, which consumes the service.
+ */
+@Component(immediate = false)
+@Service
+public class RestconfManager implements RestconfService {
+
+ private static final String RESTCONF_ROOT = "/onos/restconf";
+ private static final int THREAD_TERMINATION_TIMEOUT = 10;
+ private static final String EOL = String.format("%n");
+
+ private final int maxNumOfWorkerThreads = 5;
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ //TODO: YMS service
+ //@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ //protected YmsService ymsService;
+
+ private ListenerTracker listeners;
+
+ private ConcurrentMap<String, BlockingQueue<ObjectNode>> eventQueueList =
+ new ConcurrentHashMap<String, BlockingQueue<ObjectNode>>();
+
+ private ExecutorService workerThreadPool;
+
+ @Activate
+ protected void activate() {
+ workerThreadPool = Executors.newFixedThreadPool(maxNumOfWorkerThreads,
+ new ThreadFactoryBuilder()
+ .setNameFormat("restconf-worker")
+ .build());
+ listeners = new ListenerTracker();
+ //TODO: YMS notification
+ //listeners.addListener(ymsService, new InternalYangNotificationListener());
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ listeners.removeListeners();
+ shutdownAndAwaitTermination(workerThreadPool);
+ log.info("Stopped");
+ }
+
+ @Override
+ public ObjectNode runGetOperationOnDataResource(String uri) throws RestconfException {
+ //TODO: YMS integration
+ return null;
+ }
+
+ @Override
+ public void runPostOperationOnDataResource(String uri, ObjectNode rootNode) throws RestconfException {
+ //TODO: YMS integration
+ }
+
+ @Override
+ public void runPutOperationOnDataResource(String uri, ObjectNode rootNode) throws RestconfException {
+ //TODO: YMS integration
+ }
+
+ /**
+ * Process the delete operation on a data resource.
+ *
+ * @param uri URI of the data resource to be deleted.
+ */
+ @Override
+ public void runDeleteOperationOnDataResource(String uri) throws RestconfException {
+ //TODO: YMS integration
+ }
+
+ @Override
+ public String getRestconfRootPath() {
+ return this.RESTCONF_ROOT;
+ }
+
+ /**
+ * Creates a worker thread to listen to events and write to chunkedOutput.
+ * The worker thread blocks if no events arrive.
+ *
+ * @param streamId ID of the RESTCONF stream to subscribe
+ * @param output A string data stream
+ * @throws RestconfException if the worker thread fails to create
+ */
+ @Override
+ public void subscribeEventStream(String streamId, ChunkedOutput<String> output) throws RestconfException {
+ BlockingQueue<ObjectNode> eventQueue = new LinkedBlockingQueue<ObjectNode>();
+ if (workerThreadPool instanceof ThreadPoolExecutor) {
+ if (((ThreadPoolExecutor) workerThreadPool).getActiveCount() >= maxNumOfWorkerThreads) {
+ throw new RestconfException("no more work threads left to handle event subscription",
+ Response.Status.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ throw new RestconfException("Server ERROR: workerThreadPool NOT instanceof ThreadPoolExecutor",
+ Response.Status.INTERNAL_SERVER_ERROR);
+
+ }
+
+ workerThreadPool.submit(new EventConsumer(output, eventQueue));
+ }
+
+
+ /**
+ * Shutdown a pool cleanly if possible.
+ *
+ * @param pool an executorService
+ */
+ private void shutdownAndAwaitTermination(ExecutorService pool) {
+ pool.shutdown(); // Disable new tasks from being submitted
+ try {
+ // Wait a while for existing tasks to terminate
+ if (!pool.awaitTermination(THREAD_TERMINATION_TIMEOUT, TimeUnit.SECONDS)) {
+ pool.shutdownNow(); // Cancel currently executing tasks
+ // Wait a while for tasks to respond to being cancelled
+ if (!pool.awaitTermination(THREAD_TERMINATION_TIMEOUT, TimeUnit.SECONDS)) {
+ log.error("Pool did not terminate");
+ }
+ }
+ } catch (Exception ie) {
+ // (Re-)Cancel if current thread also interrupted
+ pool.shutdownNow();
+ // Preserve interrupt status
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ private class EventConsumer implements Runnable {
+
+ private final String queueId;
+ private final ChunkedOutput<String> output;
+ private final BlockingQueue<ObjectNode> bqueue;
+
+ public EventConsumer(ChunkedOutput<String> output, BlockingQueue<ObjectNode> q) {
+ this.queueId = Thread.currentThread().getName();
+ this.output = output;
+ this.bqueue = q;
+ eventQueueList.put(queueId, bqueue);
+ }
+
+ @Override
+ public void run() {
+ try {
+ ObjectNode chunk;
+ while ((chunk = bqueue.take()) != null) {
+ output.write(chunk.toString().concat(EOL));
+ }
+ } catch (IOException e) {
+ log.debug("chunkedOuput is closed: {}", this.bqueue.toString());
+ /*
+ * Remove queue from the queue list, so that the event producer
+ * (i.e., listener) would stop working.
+ */
+ eventQueueList.remove(this.queueId);
+ } catch (InterruptedException e) {
+ log.error("ERROR: EventConsumer: bqueue.take() has been interrupted.");
+ log.debug("EventConsumer Exception:", e);
+ } finally {
+ try {
+ output.close();
+ log.debug("EventConsumer thread terminated: {}", queueId);
+ } catch (IOException e) {
+ log.error("ERROR: EventConsumer: ", e);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * The listener class acts as the event producer for the event queues. The
+ * queues are created by the event consumer threads and are removed when the
+ * threads terminate.
+ */
+ //TODO: YMS notification
+ /*private class InternalYangNotificationListener implements YangNotificationListener {
+
+ @Override
+ public void event(YangNotificationEvent event) {
+ if (event.type() != YangNotificationEvent.Type.YANG_NOTIFICATION) {
+ // For now, we only handle YANG notification events.
+ return;
+ }
+
+ if (eventQueueList.isEmpty()) {
+ *//*
+ * There is no consumer waiting to consume, so don't have to
+ * produce this event.
+ *//*
+ return;
+ }
+
+ try {
+ *//*
+ * Put the event to every queue out there. Each queue is
+ * corresponding to an event stream session. The queue is
+ * removed when the session terminates.
+ *//*
+ for (Entry<String, BlockingQueue<ObjectNode>> entry : eventQueueList
+ .entrySet()) {
+ entry.getValue().put(event.subject().getData());
+ }
+ } catch (InterruptedException e) {
+ Log.error("ERROR", e);
+ throw new RestconfException("queue", Status.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ }*/
+}
diff --git a/protocols/restconf/server/restconfmgr/src/main/java/org/onosproject/protocol/restconf/server/restconfmanager/package-info.java b/protocols/restconf/server/restconfmgr/src/main/java/org/onosproject/protocol/restconf/server/restconfmanager/package-info.java
new file mode 100644
index 0000000..866663d
--- /dev/null
+++ b/protocols/restconf/server/restconfmgr/src/main/java/org/onosproject/protocol/restconf/server/restconfmanager/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.
+ */
+
+/**
+ * RESTCONF Service Manager implementation.
+ */
+package org.onosproject.protocol.restconf.server.restconfmanager;
diff --git a/protocols/restconf/server/rpp/BUCK b/protocols/restconf/server/rpp/BUCK
new file mode 100644
index 0000000..b4cb4a0
--- /dev/null
+++ b/protocols/restconf/server/rpp/BUCK
@@ -0,0 +1,13 @@
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+ '//lib:jersey-client',
+ '//lib:jersey-server',
+ '//lib:javax.ws.rs-api',
+ '//utils/rest:onlab-rest',
+ '//protocols/restconf/server/api:onos-protocols-restconf-server-api',
+ '//protocols/restconf/server/restconfmgr:onos-protocols-restconf-server-restconfmgr',
+]
+
+osgi_jar_with_tests (
+ deps = COMPILE_DEPS,
+)
diff --git a/protocols/restconf/server/rpp/pom.xml b/protocols/restconf/server/rpp/pom.xml
new file mode 100644
index 0000000..f14d13f
--- /dev/null
+++ b/protocols/restconf/server/rpp/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ 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.
+ -->
+<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.onosproject</groupId>
+ <artifactId>onos-restconf-server</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-restconf-server-rpp</artifactId>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <web.context>/onos/restconf</web.context>
+ <api.version>1.0.0</api.version>
+ <api.title>YANG RESTCONF Protocol Stack</api.title>
+ <api.description>
+ RESTCONF Protocol Proxy
+ </api.description>
+ <api.package>org.onosproject.protocol.restconf.server.rpp</api.package>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-restconf-server-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-restconf-server-restconfmanager</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-rest</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-rest</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-dhcp-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>2.22.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-common</artifactId>
+ <version>2.22.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-misc</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ <version>1.9.8</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <_wab>src/main/webapp/</_wab>
+ <Include-Resource>
+ WEB-INF/classes/apidoc/swagger.json=target/swagger.json,
+ {maven-resources}
+ </Include-Resource>
+ <Bundle-SymbolicName>
+ ${project.groupId}.${project.artifactId}
+ </Bundle-SymbolicName>
+ <Import-Package>
+ *,org.glassfish.jersey.servlet
+ </Import-Package>
+ <Web-ContextPath>${web.context}</Web-ContextPath>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+
+</project>
diff --git a/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/RestconfProtocolProxy.java b/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/RestconfProtocolProxy.java
new file mode 100644
index 0000000..35a35e9
--- /dev/null
+++ b/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/RestconfProtocolProxy.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.
+ */
+package org.onosproject.protocol.restconf.server.rpp;
+
+import org.onlab.rest.AbstractWebApplication;
+
+import java.util.Set;
+
+/**
+ * RESTCONF Server front-end application.
+ */
+public class RestconfProtocolProxy extends AbstractWebApplication {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return getClasses(RestconfWebResource.class);
+ }
+}
diff --git a/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/RestconfWebResource.java b/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/RestconfWebResource.java
new file mode 100644
index 0000000..f2608a3
--- /dev/null
+++ b/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/RestconfWebResource.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.
+ */
+
+package org.onosproject.protocol.restconf.server.rpp;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.glassfish.jersey.server.ChunkedOutput;
+import org.onosproject.protocol.restconf.server.api.RestconfException;
+import org.onosproject.protocol.restconf.server.api.RestconfService;
+import org.onosproject.rest.AbstractWebResource;
+import org.slf4j.Logger;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/*
+ * This class is the main implementation of the RESTCONF Protocol
+ * Proxy module. Currently it only handles some basic operations
+ * on data resource nodes. However, the design intention is to
+ * create a code structure that allows new methods/functionality
+ * to be easily added in future releases.
+ */
+
+/**
+ * Implementation of the RESTCONF Protocol Proxy module.
+ */
+@Path("/")
+public class RestconfWebResource extends AbstractWebResource {
+
+ @Context
+ UriInfo uriInfo;
+
+ private final RestconfService service = get(RestconfService.class);
+ private final Logger log = getLogger(getClass());
+
+ /**
+ * Handles a RESTCONF GET operation against a target data resource. If the
+ * operation is successful, the JSON presentation of the resource plus HTTP
+ * status code "200 OK" is returned. Otherwise, HTTP error status code
+ * "400 Bad Request" is returned.
+ *
+ * @param uriString URI of the data resource.
+ * @return HTTP response
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("data/{identifier : .+}")
+ public Response handleGetRequest(@PathParam("identifier") String uriString) {
+
+ log.debug("handleGetRequest: {}", uriString);
+
+ try {
+ ObjectNode node = service.runGetOperationOnDataResource(uriString);
+ return ok(node).build();
+ } catch (RestconfException e) {
+ log.error("ERROR: handleGetRequest: {}", e.getMessage());
+ log.debug("Exception in handleGetRequest:", e);
+ return e.getResponse();
+ }
+ }
+
+ /**
+ * Handles the RESTCONF Event Notification Subscription request. If the
+ * subscription is successful, a ChunkedOutput stream is created and returned
+ * to the caller.
+ * <P></P>
+ * This function is not blocked on streaming the data (so that it can handle
+ * other incoming requests). Instead, a worker thread running in the background
+ * does the data streaming. If errors occur during streaming, the worker thread
+ * calls ChunkedOutput.close() to disconnect the session and terminates itself.
+ *
+ * @param streamId Event stream ID
+ * @return A string data stream over HTTP keep-alive session
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("streams/{streamId}")
+ public ChunkedOutput<String> handleNotificationRegistration(@PathParam("streamId") String streamId) {
+ final ChunkedOutput<String> output = new ChunkedOutput<String>(String.class);
+ try {
+ service.subscribeEventStream(streamId, output);
+ } catch (RestconfException e) {
+ log.error("ERROR: handleNotificationRegistration: {}", e.getMessage());
+ log.debug("Exception in handleNotificationRegistration:", e);
+ try {
+ output.close();
+ } catch (IOException ex) {
+ log.error("ERROR: handleNotificationRegistration:", ex);
+ }
+ }
+
+ return output;
+ }
+
+ /**
+ * Handles a RESTCONF POST operation against a data resource. If the
+ * operation is successful, HTTP status code "201 Created" is returned
+ * and there is no response message-body. If the data resource already
+ * exists, then the HTTP status code "409 Conflict" is returned.
+ *
+ * @param uriString URI of the data resource
+ * @param stream Input JSON object
+ * @return HTTP response
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("data/{identifier : .+}")
+ public Response handlePostRequest(@PathParam("identifier") String uriString, InputStream stream) {
+
+ log.debug("handlePostRequest: {}", uriString);
+
+ try {
+ ObjectNode rootNode = (ObjectNode) mapper().readTree(stream);
+
+ service.runPostOperationOnDataResource(uriString, rootNode);
+ return Response.created(uriInfo.getRequestUri()).build();
+ } catch (JsonProcessingException e) {
+ log.error("ERROR: handlePostRequest ", e);
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ } catch (RestconfException e) {
+ log.error("ERROR: handlePostRequest: {}", e.getMessage());
+ log.debug("Exception in handlePostRequest:", e);
+ return e.getResponse();
+ } catch (IOException ex) {
+ log.error("ERROR: handlePostRequest ", ex);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ }
+
+ /**
+ * Handles a RESTCONF PUT operation against a data resource. If a new
+ * resource is successfully created, then the HTTP status code "201 Created"
+ * is returned. If an existing resource is modified, then the HTTP
+ * status code "204 No Content" is returned. If the input JSON payload
+ * contains errors, then "400 Bad Request" is returned. If an exception
+ * occurs during the operation, the status code enclosed in
+ * the RestconfException object, such as "500 Internal Server Error",
+ * is returned.
+ *
+ * @param uriString URI of the data resource.
+ * @param stream Input JSON object
+ * @return HTTP response
+ */
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("data/{identifier : .+}")
+ public Response handlePutRequest(@PathParam("identifier") String uriString, InputStream stream) {
+
+ log.debug("handlePutRequest: {}", uriString);
+
+ try {
+ ObjectNode rootNode = (ObjectNode) mapper().readTree(stream);
+
+ service.runPutOperationOnDataResource(uriString, rootNode);
+ return Response.created(uriInfo.getRequestUri()).build();
+ } catch (JsonProcessingException e) {
+ log.error("ERROR: handlePutRequest ", e);
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ } catch (RestconfException e) {
+ log.error("ERROR: handlePutRequest: {}", e.getMessage());
+ log.debug("Exception in handlePutRequest:", e);
+ return e.getResponse();
+ } catch (IOException ex) {
+ log.error("ERROR: handlePutRequest ", ex);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ }
+
+ /**
+ * Handles the RESTCONF DELETION Operation against a data resource. If the
+ * resource is successfully deleted, the HTTP status code "204 No Content"
+ * is returned in the response. If an exception occurs, then the
+ * HTTP status code enclosed in the RestconfException object is
+ * returned.
+ *
+ * @param uriString URI of the data resource to be deleted.
+ * @return HTTP response
+ */
+ @DELETE
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("data/{identifier : .+}")
+ public Response handleDeleteRequest(@PathParam("identifier") String uriString) {
+
+ log.debug("handleDeleteRequest: {}", uriString);
+
+ try {
+ service.runDeleteOperationOnDataResource(uriString);
+ return Response.ok().build();
+ } catch (RestconfException e) {
+ log.error("ERROR: handleDeleteRequest: {}", e.getMessage());
+ log.debug("Exception in handleDeleteRequest:", e);
+ return e.getResponse();
+ }
+ }
+
+}
diff --git a/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/package-info.java b/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/package-info.java
new file mode 100644
index 0000000..01f56f2
--- /dev/null
+++ b/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.
+ */
+
+/**
+ * RESTCONF Protocol Proxy implementation.
+ */
+package org.onosproject.protocol.restconf.server.rpp;
diff --git a/protocols/restconf/server/rpp/src/main/webapp/WEB-INF/web.xml b/protocols/restconf/server/rpp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..c738da9
--- /dev/null
+++ b/protocols/restconf/server/rpp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2016-present Open Networking Laboratory
+ ~
+ ~ 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.
+ -->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ id="ONOS" version="2.5">
+ <display-name>ONOS RESTCONF Protocol Proxy</display-name>
+
+ <servlet>
+ <servlet-name>RESTCONF Protocol Proxy</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.onosproject.protocol.restconf.server.rpp.RestconfProtocolProxy</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>RESTCONF Protocol Proxy</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>