netconf chunked framing v2

Change-Id: I93fad5c44315960ca6aebe5b0944947ac8bf6a51
diff --git a/protocols/netconf/ctl/src/test/java/org/onosproject/netconf/ctl/impl/NetconfSessionImplTest.java b/protocols/netconf/ctl/src/test/java/org/onosproject/netconf/ctl/impl/NetconfSessionImplTest.java
index 8fdd5ff..1b5e7fa 100644
--- a/protocols/netconf/ctl/src/test/java/org/onosproject/netconf/ctl/impl/NetconfSessionImplTest.java
+++ b/protocols/netconf/ctl/src/test/java/org/onosproject/netconf/ctl/impl/NetconfSessionImplTest.java
@@ -27,7 +27,6 @@
 import java.io.File;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
@@ -35,6 +34,7 @@
 import java.util.concurrent.FutureTask;
 import java.util.regex.Pattern;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.server.Command;
 import org.apache.sshd.server.SshServer;
@@ -53,7 +53,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.ImmutableList;
 
 /**
  * Unit tests for NetconfSession.
@@ -89,22 +88,10 @@
                     + "</edit-config>\n"
                     + "</rpc>]]>]]>";
 
-    static final List<String> DEFAULT_CAPABILITIES = ImmutableList.<String>builder()
-            .add("urn:ietf:params:netconf:base:1.0")
-            .add("urn:ietf:params:netconf:base:1.1")
-            .add("urn:ietf:params:netconf:capability:writable-running:1.0")
-            .add("urn:ietf:params:netconf:capability:candidate:1.0")
-            .add("urn:ietf:params:netconf:capability:startup:1.0")
-            .add("urn:ietf:params:netconf:capability:rollback-on-error:1.0")
-            .add("urn:ietf:params:netconf:capability:interleave:1.0")
-            .add("urn:ietf:params:netconf:capability:notification:1.0")
-            .add("urn:ietf:params:netconf:capability:validate:1.0")
-            .add("urn:ietf:params:netconf:capability:validate:1.1")
-            .build();
-
-
     private static NetconfSession session1;
     private static NetconfSession session2;
+    private static NetconfSession session3;
+    private static NetconfSession session4;
     private static SshServer sshServerNetconf;
 
     @BeforeClass
@@ -132,17 +119,30 @@
         NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo(
                 TEST_USERNAME, TEST_PASSWORD, Ip4Address.valueOf(TEST_HOSTNAME), PORT_NUMBER);
 
-        session1 = new NetconfSessionImpl(deviceInfo);
+        session1 = new NetconfSessionImpl(deviceInfo, ImmutableList.of("urn:ietf:params:netconf:base:1.0"));
         log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session1.getSessionId());
         assertTrue("Incorrect sessionId", !session1.getSessionId().equalsIgnoreCase("-1"));
         assertTrue("Incorrect sessionId", !session1.getSessionId().equalsIgnoreCase("0"));
-        assertThat(session1.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES.toArray()));
-
-        session2 = new NetconfSessionImpl(deviceInfo);
+        assertThat(session1.getDeviceCapabilitiesSet(), containsInAnyOrder(
+                NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES.toArray()));
+        session2 = new NetconfSessionImpl(deviceInfo, ImmutableList.of("urn:ietf:params:netconf:base:1.0"));
         log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session2.getSessionId());
         assertTrue("Incorrect sessionId", !session2.getSessionId().equalsIgnoreCase("-1"));
         assertTrue("Incorrect sessionId", !session2.getSessionId().equalsIgnoreCase("0"));
-        assertThat(session2.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES.toArray()));
+        assertThat(session2.getDeviceCapabilitiesSet(), containsInAnyOrder(
+                NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES.toArray()));
+        session3 = new NetconfSessionImpl(deviceInfo);
+        log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session3.getSessionId());
+        assertTrue("Incorrect sessionId", !session3.getSessionId().equalsIgnoreCase("-1"));
+        assertTrue("Incorrect sessionId", !session3.getSessionId().equalsIgnoreCase("0"));
+        assertThat(session3.getDeviceCapabilitiesSet(), containsInAnyOrder(
+                NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES_1_1.toArray()));
+        session4 = new NetconfSessionImpl(deviceInfo);
+        log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session4.getSessionId());
+        assertTrue("Incorrect sessionId", !session4.getSessionId().equalsIgnoreCase("-1"));
+        assertTrue("Incorrect sessionId", !session4.getSessionId().equalsIgnoreCase("0"));
+        assertThat(session4.getDeviceCapabilitiesSet(), containsInAnyOrder(
+                NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES_1_1.toArray()));
     }
 
     @AfterClass
@@ -153,6 +153,12 @@
         if (session2 != null) {
             session2.close();
         }
+        if (session3 != null) {
+            session3.close();
+        }
+        if (session4 != null) {
+            session4.close();
+        }
 
         sshServerNetconf.stop();
     }
@@ -163,8 +169,23 @@
         assertNotNull("Incorrect sessionId", session1.getSessionId());
         try {
             assertTrue("NETCONF edit-config command failed",
-                       session1.editConfig(DatastoreId.RUNNING,
-                                           null, SAMPLE_REQUEST));
+                    session1.editConfig(DatastoreId.RUNNING,
+                            null, SAMPLE_REQUEST));
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF edit-config test failed: " + e.getMessage());
+        }
+        log.info("Finishing edit-config async");
+    }
+
+    @Test
+    public void testEditConfigRequestWithChunkedFraming() {
+        log.info("Starting edit-config async");
+        assertNotNull("Incorrect sessionId", session3.getSessionId());
+        try {
+            assertTrue("NETCONF edit-config command failed",
+                    session3.editConfig(DatastoreId.RUNNING,
+                            null, SAMPLE_REQUEST));
         } catch (NetconfException e) {
             e.printStackTrace();
             fail("NETCONF edit-config test failed: " + e.getMessage());
@@ -178,7 +199,21 @@
         assertNotNull("Incorrect sessionId", session1.getSessionId());
         try {
             assertTrue("NETCONF edit-config command failed",
-                       session1.editConfig(EDIT_CONFIG_REQUEST));
+                    session1.editConfig(NetconfSessionMinaImplTest.EDIT_CONFIG_REQUEST));
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF edit-config test failed: " + e.getMessage());
+        }
+        log.info("Finishing edit-config async");
+    }
+
+    @Test
+    public void testEditConfigRequestWithOnlyNewConfigurationWithChunkedFraming() {
+        log.info("Starting edit-config async");
+        assertNotNull("Incorrect sessionId", session3.getSessionId());
+        try {
+            assertTrue("NETCONF edit-config command failed",
+                    session3.editConfig(NetconfSessionMinaImplTest.EDIT_CONFIG_REQUEST));
         } catch (NetconfException e) {
             e.printStackTrace();
             fail("NETCONF edit-config test failed: " + e.getMessage());
@@ -192,7 +227,21 @@
         assertNotNull("Incorrect sessionId", session1.getSessionId());
         try {
             assertFalse("NETCONF delete-config command failed",
-                        session1.deleteConfig(DatastoreId.RUNNING));
+                    session1.deleteConfig(DatastoreId.RUNNING));
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF delete-config test failed: " + e.getMessage());
+        }
+        log.info("Finishing delete-config async");
+    }
+
+    @Test
+    public void testDeleteConfigRequestWithRunningTargetConfigurationWithChunkedFraming() {
+        log.info("Starting delete-config async");
+        assertNotNull("Incorrect sessionId", session3.getSessionId());
+        try {
+            assertFalse("NETCONF delete-config command failed",
+                    session3.deleteConfig(DatastoreId.RUNNING));
         } catch (NetconfException e) {
             e.printStackTrace();
             fail("NETCONF delete-config test failed: " + e.getMessage());
@@ -206,8 +255,23 @@
         assertNotNull("Incorrect sessionId", session1.getSessionId());
         try {
             assertTrue("NETCONF copy-config command failed",
-                       session1.copyConfig(DatastoreId.RUNNING,
-                                           DatastoreId.CANDIDATE));
+                    session1.copyConfig(DatastoreId.RUNNING,
+                            DatastoreId.CANDIDATE));
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF copy-config test failed: " + e.getMessage());
+        }
+        log.info("Finishing copy-config async");
+    }
+
+    @Test
+    public void testCopyConfigRequestWithChunkedFraming() {
+        log.info("Starting copy-config async");
+        assertNotNull("Incorrect sessionId", session3.getSessionId());
+        try {
+            assertTrue("NETCONF copy-config command failed",
+                    session3.copyConfig(DatastoreId.RUNNING,
+                            DatastoreId.CANDIDATE));
         } catch (NetconfException e) {
             e.printStackTrace();
             fail("NETCONF copy-config test failed: " + e.getMessage());
@@ -221,8 +285,23 @@
         assertNotNull("Incorrect sessionId", session1.getSessionId());
         try {
             assertTrue("NETCONF copy-config command failed",
-                       session1.copyConfig(DatastoreId.RUNNING,
-                                           "<configuration><device-specific/></configuration>"));
+                    session1.copyConfig(DatastoreId.RUNNING,
+                            "<configuration><device-specific/></configuration>"));
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF copy-config test failed: " + e.getMessage());
+        }
+        log.info("Finishing copy-config XML async");
+    }
+
+    @Test
+    public void testCopyConfigXmlWithChunkedFraming() {
+        log.info("Starting copy-config XML async");
+        assertNotNull("Incorrect sessionId", session3.getSessionId());
+        try {
+            assertTrue("NETCONF copy-config command failed",
+                    session3.copyConfig(DatastoreId.RUNNING,
+                            "<configuration><device-specific/></configuration>"));
         } catch (NetconfException e) {
             e.printStackTrace();
             fail("NETCONF copy-config test failed: " + e.getMessage());
@@ -237,10 +316,27 @@
         assertNotNull("Incorrect sessionId", session1.getSessionId());
         try {
             assertTrue("NETCONF copy-config command failed",
-                       session1.copyConfig(DatastoreId.RUNNING,
-                                           "<config>"
-                                           + "<configuration><device-specific/></configuration>"
-                                         + "</config>"));
+                    session1.copyConfig(DatastoreId.RUNNING,
+                            "<config>"
+                                    + "<configuration><device-specific/></configuration>"
+                                    + "</config>"));
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF copy-config test failed: " + e.getMessage());
+        }
+        log.info("Finishing copy-config bare XML async");
+    }
+
+    @Test
+    public void testCopyConfigBareXmlWithChunkedFraming() {
+        log.info("Starting copy-config bare XML async");
+        assertNotNull("Incorrect sessionId", session3.getSessionId());
+        try {
+            assertTrue("NETCONF copy-config command failed",
+                    session3.copyConfig(DatastoreId.RUNNING,
+                            "<config>"
+                                    + "<configuration><device-specific/></configuration>"
+                                    + "</config>"));
         } catch (NetconfException e) {
             e.printStackTrace();
             fail("NETCONF copy-config test failed: " + e.getMessage());
@@ -254,10 +350,32 @@
         assertNotNull("Incorrect sessionId", session1.getSessionId());
         try {
             assertTrue("NETCONF get-config running command failed. ",
-                       GET_REPLY_PATTERN.matcher(session1.getConfig(RUNNING, SAMPLE_REQUEST)).matches());
+                    NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session1.getConfig(RUNNING,
+                            SAMPLE_REQUEST)).matches());
 
             assertTrue("NETCONF get-config candidate command failed. ",
-                       GET_REPLY_PATTERN.matcher(session1.getConfig(CANDIDATE, SAMPLE_REQUEST)).matches());
+                    NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session1.getConfig(CANDIDATE,
+                            SAMPLE_REQUEST)).matches());
+
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF get-config test failed: " + e.getMessage());
+        }
+        log.info("Finishing get-config async");
+    }
+
+    @Test
+    public void testGetConfigRequestWithChunkedFraming() {
+        log.info("Starting get-config async");
+        assertNotNull("Incorrect sessionId", session3.getSessionId());
+        try {
+            assertTrue("NETCONF get-config running command failed. ",
+                    NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session3.getConfig(RUNNING,
+                            SAMPLE_REQUEST)).matches());
+
+            assertTrue("NETCONF get-config candidate command failed. ",
+                    NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session3.getConfig(CANDIDATE,
+                            SAMPLE_REQUEST)).matches());
 
         } catch (NetconfException e) {
             e.printStackTrace();
@@ -272,7 +390,23 @@
         assertNotNull("Incorrect sessionId", session1.getSessionId());
         try {
             assertTrue("NETCONF get running command failed. ",
-                       GET_REPLY_PATTERN.matcher(session1.get(SAMPLE_REQUEST, null)).matches());
+                    NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session1.get(SAMPLE_REQUEST,
+                            null)).matches());
+
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF get test failed: " + e.getMessage());
+        }
+        log.info("Finishing get async");
+    }
+
+    @Test
+    public void testGetRequestWithChunkedFraming() {
+        log.info("Starting get async");
+        assertNotNull("Incorrect sessionId", session3.getSessionId());
+        try {
+            assertTrue("NETCONF get running command failed. ",
+                    NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session3.get(SAMPLE_REQUEST, null)).matches());
 
         } catch (NetconfException e) {
             e.printStackTrace();
@@ -295,6 +429,19 @@
     }
 
     @Test
+    public void testLockRequestWithChunkedFraming() {
+        log.info("Starting lock async");
+        assertNotNull("Incorrect sessionId", session3.getSessionId());
+        try {
+            assertTrue("NETCONF lock request failed", session3.lock());
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF lock test failed: " + e.getMessage());
+        }
+        log.info("Finishing lock async");
+    }
+
+    @Test
     public void testUnLockRequest() {
         log.info("Starting unlock async");
         assertNotNull("Incorrect sessionId", session1.getSessionId());
@@ -307,6 +454,19 @@
         log.info("Finishing unlock async");
     }
 
+    @Test
+    public void testUnLockRequestWithChunkedFraming() {
+        log.info("Starting unlock async");
+        assertNotNull("Incorrect sessionId", session3.getSessionId());
+        try {
+            assertTrue("NETCONF unlock request failed", session3.unlock());
+        } catch (NetconfException e) {
+            e.printStackTrace();
+            fail("NETCONF unlock test failed: " + e.getMessage());
+        }
+        log.info("Finishing unlock async");
+    }
+
 
     @Test
     public void testConcurrentSameSessionAccess() throws InterruptedException {
@@ -335,6 +495,32 @@
     }
 
     @Test
+    public void testConcurrentSameSessionAccessWithChunkedFraming() throws InterruptedException {
+        NCCopyConfigCallable testCopyConfig1 = new NCCopyConfigCallable(session3, RUNNING, "candidate");
+        NCCopyConfigCallable testCopyConfig2 = new NCCopyConfigCallable(session3, RUNNING, "startup");
+
+        FutureTask<Boolean> futureCopyConfig1 = new FutureTask<>(testCopyConfig1);
+        FutureTask<Boolean> futureCopyConfig2 = new FutureTask<>(testCopyConfig2);
+
+        ExecutorService executor = Executors.newFixedThreadPool(2);
+        log.info("Starting concurrent execution of copy-config through same session");
+        executor.execute(futureCopyConfig1);
+        executor.execute(futureCopyConfig2);
+
+        int count = 0;
+        while (count < 10) {
+            if (futureCopyConfig1.isDone() && futureCopyConfig2.isDone()) {
+                executor.shutdown();
+                log.info("Finished concurrent same session execution");
+                return;
+            }
+            Thread.sleep(100L);
+            count++;
+        }
+        fail("NETCONF test failed to complete.");
+    }
+
+    @Test
     public void test2SessionAccess() throws InterruptedException {
         NCCopyConfigCallable testCopySession1 = new NCCopyConfigCallable(session1, RUNNING, "candidate");
         NCCopyConfigCallable testCopySession2 = new NCCopyConfigCallable(session2, RUNNING, "candidate");
@@ -360,9 +546,39 @@
         fail("NETCONF test failed to complete.");
     }
 
+    @Test
+    public void test2SessionAccessWithChunkedFraming() throws InterruptedException {
+        NCCopyConfigCallable testCopySession1 = new NCCopyConfigCallable(session3, RUNNING, "candidate");
+        NCCopyConfigCallable testCopySession2 = new NCCopyConfigCallable(session4, RUNNING, "candidate");
 
-    public static String getTestHelloReply(Optional<Long> sessionId) {
-        return getTestHelloReply(DEFAULT_CAPABILITIES, sessionId);
+        FutureTask<Boolean> futureCopySession1 = new FutureTask<>(testCopySession1);
+        FutureTask<Boolean> futureCopySession2 = new FutureTask<>(testCopySession2);
+
+        ExecutorService executor = Executors.newFixedThreadPool(2);
+        log.info("Starting concurrent execution of copy-config through 2 different sessions");
+        executor.execute(futureCopySession1);
+        executor.execute(futureCopySession2);
+
+        int count = 0;
+        while (count < 10) {
+            if (futureCopySession1.isDone() && futureCopySession2.isDone()) {
+                executor.shutdown();
+                log.info("Finished concurrent 2 session execution");
+                return;
+            }
+            Thread.sleep(100L);
+            count++;
+        }
+        fail("NETCONF test failed to complete.");
+    }
+
+
+    public static String getTestHelloReply(Optional<Long> sessionId, boolean useChunkedFraming) {
+        if (useChunkedFraming) {
+            return getTestHelloReply(NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES_1_1, sessionId);
+        } else {
+            return getTestHelloReply(NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES, sessionId);
+        }
     }
 
     public static String getTestHelloReply(Collection<String> capabilities, Optional<Long> sessionId) {
@@ -414,11 +630,21 @@
 
     public static final Pattern HELLO_REQ_PATTERN =
             Pattern.compile("(<\\?xml).*"
-                    + "(<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
-                    + "( *)(<capabilities>)\\R?"
-                    + "( *)(<capability>urn:ietf:params:netconf:base:1.0</capability>)\\R?"
-                    + "( *)(</capabilities>)\\R?"
-                    + "(</hello>)\\R? *",
+                            + "(<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                            + "( *)(<capabilities>)\\R?"
+                            + "( *)(<capability>urn:ietf:params:netconf:base:1.0</capability>)\\R?"
+                            + "( *)(</capabilities>)\\R?"
+                            + "(</hello>)\\R? *",
+                    Pattern.DOTALL);
+
+    public static final Pattern HELLO_REQ_PATTERN_1_1 =
+            Pattern.compile("(<\\?xml).*"
+                            + "(<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+                            + "( *)(<capabilities>)\\R?"
+                            + "( *)(<capability>urn:ietf:params:netconf:base:1.0</capability>)\\R?"
+                            + "( *)(<capability>urn:ietf:params:netconf:base:1.1</capability>)\\R?"
+                            + "( *)(</capabilities>)\\R?"
+                            + "(</hello>)\\R? *",
                     Pattern.DOTALL);
 
     public static final Pattern EDIT_CONFIG_REQ_PATTERN =
@@ -426,8 +652,8 @@
                     + "(<rpc message-id=\")[0-9]*(\") *(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
                     + "(<edit-config>)\\R?"
                     + "(<target>\\R?((<" + DatastoreId.CANDIDATE.toString() + "/>)|"
-                                    + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
-                                    + "(<" + DatastoreId.STARTUP.toString() + "/>))\\R?</target>)\\R?"
+                    + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
+                    + "(<" + DatastoreId.STARTUP.toString() + "/>))\\R?</target>)\\R?"
                     + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
                     + ".*"
                     + "(</config>)\\R?(</edit-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
@@ -435,23 +661,23 @@
 
     public static final Pattern LOCK_REQ_PATTERN =
             Pattern.compile("(<\\?xml).*"
-                                    + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
-                                    + "message-id=\")[0-9]*(\">)\\R?"
-                                    + "(<lock>)\\R?"
-                                    + "(<target>\\R?((<" + DatastoreId.CANDIDATE.toString() + "/>)|"
-                                    + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
-                                    + "(<" + DatastoreId.STARTUP.toString() + "/>))\\R?</target>)\\R?"
-                                    + "(</lock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
+                    + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
+                    + "message-id=\")[0-9]*(\">)\\R?"
+                    + "(<lock>)\\R?"
+                    + "(<target>\\R?((<" + DatastoreId.CANDIDATE.toString() + "/>)|"
+                    + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
+                    + "(<" + DatastoreId.STARTUP.toString() + "/>))\\R?</target>)\\R?"
+                    + "(</lock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
 
     public static final Pattern UNLOCK_REQ_PATTERN =
             Pattern.compile("(<\\?xml).*"
-                                    + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
-                                    + "message-id=\")[0-9]*(\">)\\R?"
-                                    + "(<unlock>)\\R?"
-                                    + "(<target>\\R?((<" + DatastoreId.CANDIDATE.toString() + "/>)|"
-                                    + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
-                                    + "(<" + DatastoreId.STARTUP.toString() + "/>))\\R?</target>)\\R?"
-                                    + "(</unlock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
+                    + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
+                    + "message-id=\")[0-9]*(\">)\\R?"
+                    + "(<unlock>)\\R?"
+                    + "(<target>\\R?((<" + DatastoreId.CANDIDATE.toString() + "/>)|"
+                    + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
+                    + "(<" + DatastoreId.STARTUP.toString() + "/>))\\R?</target>)\\R?"
+                    + "(</unlock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
 
     public static final Pattern COPY_CONFIG_REQ_PATTERN =
             Pattern.compile("(<\\?xml).*"
@@ -459,17 +685,17 @@
                     + "(<copy-config>)\\R?"
                     + "(<target>\\R?"
                     + "("
-                        + "(<" + DatastoreId.CANDIDATE.toString() + "/>)|"
-                        + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
-                        + "(<" + DatastoreId.STARTUP.toString() + "/>)"
+                    + "(<" + DatastoreId.CANDIDATE.toString() + "/>)|"
+                    + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
+                    + "(<" + DatastoreId.STARTUP.toString() + "/>)"
                     + ")\\R?"
                     + "</target>)\\R?"
                     + "(<source>)\\R?"
                     + "("
-                        + "(<config>)(.*)(</config>)|"
-                        + "(<" + DatastoreId.CANDIDATE.toString() + "/>)|"
-                        + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
-                        + "(<" + DatastoreId.STARTUP.toString() + "/>)"
+                    + "(<config>)(.*)(</config>)|"
+                    + "(<" + DatastoreId.CANDIDATE.toString() + "/>)|"
+                    + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
+                    + "(<" + DatastoreId.STARTUP.toString() + "/>)"
                     + ")\\R?"
                     + "(</source>)\\R?"
                     + "(</copy-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
@@ -478,18 +704,14 @@
             Pattern.compile("(<\\?xml).*"
                     + "(<rpc message-id=\")[0-9]*(\"  xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
                     + "(<get-config>)\\R?" + "(<source>)\\R?((<"
-                                    + DatastoreId.CANDIDATE.toString()
-                                    + "/>)|(<" + DatastoreId.RUNNING.toString()
-                                    + "/>)|(<" + DatastoreId.STARTUP.toString()
-                                    + "/>))\\R?(</source>)\\R?"
+                    + DatastoreId.CANDIDATE.toString()
+                    + "/>)|(<" + DatastoreId.RUNNING.toString()
+                    + "/>)|(<" + DatastoreId.STARTUP.toString()
+                    + "/>))\\R?(</source>)\\R?"
                     + "(<filter type=\"subtree\">).*(</filter>)\\R?"
                     + "(</get-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
 
-    public static final Pattern GET_REPLY_PATTERN =
-            Pattern.compile("(<\\?xml).*"
-                    + "(<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\")[0-9]*(\">)\\R?"
-                    + "(<data>).*(</data>)\\R?"
-                    + "(</rpc-reply>)\\R?", Pattern.DOTALL);
+
 
     public static final Pattern GET_REQ_PATTERN =
             Pattern.compile("(<\\?xml).*"
@@ -514,4 +736,4 @@
             return session.copyConfig(target, source);
         }
     }
-}
+}
\ No newline at end of file