Bug:1253 - Fix NPE in config pusher
[controller.git] / opendaylight / netconf / config-persister-impl / src / main / java / org / opendaylight / controller / netconf / persist / impl / ConfigPusher.java
index ed5a3a97a4c67809e75857ba77409eb695e00535..eddad8b4c7c1df593c45a5f829c3c56828339e18 100644 (file)
@@ -8,14 +8,28 @@
 
 package org.opendaylight.controller.netconf.persist.impl;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
 import com.google.common.base.Stopwatch;
 import com.google.common.collect.Collections2;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.concurrent.Immutable;
 import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.mapping.api.Capability;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
@@ -24,7 +38,6 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
 import org.opendaylight.controller.netconf.util.NetconfUtil;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -32,18 +45,6 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
-import javax.annotation.concurrent.Immutable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.TimeUnit;
-
 @Immutable
 public class ConfigPusher {
     private static final Logger logger = LoggerFactory.getLogger(ConfigPusher.class);
@@ -59,7 +60,7 @@ public class ConfigPusher {
         this.conflictingVersionTimeoutMillis = conflictingVersionTimeoutMillis;
     }
 
-    public synchronized LinkedHashMap<ConfigSnapshotHolder, EditAndCommitResponse> pushConfigs(List<ConfigSnapshotHolder> configs) {
+    public synchronized LinkedHashMap<ConfigSnapshotHolder, EditAndCommitResponse> pushConfigs(List<ConfigSnapshotHolder> configs) throws NetconfDocumentedException {
         logger.debug("Last config snapshots to be pushed to netconf: {}", configs);
         LinkedHashMap<ConfigSnapshotHolder, EditAndCommitResponse> result = new LinkedHashMap<>();
         // start pushing snapshots:
@@ -78,11 +79,15 @@ public class ConfigPusher {
      * is caught, whole process is retried - new service instance need to be obtained from the factory. Closes
      * {@link NetconfOperationService} after each use.
      */
-    private synchronized EditAndCommitResponse pushConfigWithConflictingVersionRetries(ConfigSnapshotHolder configSnapshotHolder) {
+    private synchronized EditAndCommitResponse pushConfigWithConflictingVersionRetries(ConfigSnapshotHolder configSnapshotHolder) throws NetconfDocumentedException {
         ConflictingVersionException lastException;
         Stopwatch stopwatch = new Stopwatch().start();
         do {
-            try (NetconfOperationService operationService = getOperationServiceWithRetries(configSnapshotHolder.getCapabilities(), configSnapshotHolder.toString())) {
+            String idForReporting = configSnapshotHolder.toString();
+            SortedSet<String> expectedCapabilities = checkNotNull(configSnapshotHolder.getCapabilities(),
+                    "Expected capabilities must not be null - %s, check %s", idForReporting,
+                    configSnapshotHolder.getClass().getName());
+            try (NetconfOperationService operationService = getOperationServiceWithRetries(expectedCapabilities, idForReporting)) {
                 return pushConfig(configSnapshotHolder, operationService);
             } catch (ConflictingVersionException e) {
                 lastException = e;
@@ -110,6 +115,8 @@ public class ConfigPusher {
     }
 
     private static class NotEnoughCapabilitiesException extends Exception {
+        private static final long serialVersionUID = 1L;
+
         private NotEnoughCapabilitiesException(String message, Throwable cause) {
             super(message, cause);
         }
@@ -139,7 +146,7 @@ public class ConfigPusher {
         } else {
             serviceCandidate.close();
             logger.trace("Netconf server did not provide required capabilities for {} " +
-                            "Expected but not found: {}, all expected {}, current {}",
+                    "Expected but not found: {}, all expected {}, current {}",
                     idForReporting, notFoundDiff, expectedCapabilities, serviceCandidate.getCapabilities()
             );
             throw new NotEnoughCapabilitiesException("Not enough capabilities for " + idForReporting + ". Expected but not found: " + notFoundDiff);
@@ -177,7 +184,7 @@ public class ConfigPusher {
      * @throws java.lang.RuntimeException  if edit-config or commit fails otherwise
      */
     private synchronized EditAndCommitResponse pushConfig(ConfigSnapshotHolder configSnapshotHolder, NetconfOperationService operationService)
-            throws ConflictingVersionException {
+            throws ConflictingVersionException, NetconfDocumentedException {
 
         Element xmlToBePersisted;
         try {
@@ -209,7 +216,7 @@ public class ConfigPusher {
         return new EditAndCommitResponse(editResponseMessage, commitResponseMessage);
     }
 
-    private NetconfOperation findOperation(NetconfMessage request, NetconfOperationService operationService) {
+    private NetconfOperation findOperation(NetconfMessage request, NetconfOperationService operationService) throws NetconfDocumentedException {
         TreeMap<HandlingPriority, NetconfOperation> allOperations = new TreeMap<>();
         Set<NetconfOperation> netconfOperations = operationService.getNetconfOperations();
         if (netconfOperations.isEmpty()) {
@@ -228,7 +235,7 @@ public class ConfigPusher {
 
     private Document sendRequestGetResponseCheckIsOK(NetconfMessage request, NetconfOperationService operationService,
                                                      String operationNameForReporting, String configIdForReporting)
-            throws ConflictingVersionException {
+            throws ConflictingVersionException, NetconfDocumentedException {
 
         NetconfOperation operation = findOperation(request, operationService);
         Document response;
@@ -245,10 +252,10 @@ public class ConfigPusher {
     }
 
     // load editConfig.xml template, populate /rpc/edit-config/config with parameter
-    private static NetconfMessage createEditConfigMessage(Element dataElement) {
+    private static NetconfMessage createEditConfigMessage(Element dataElement) throws NetconfDocumentedException {
         String editConfigResourcePath = "/netconfOp/editConfig.xml";
         try (InputStream stream = ConfigPersisterNotificationHandler.class.getResourceAsStream(editConfigResourcePath)) {
-            Preconditions.checkNotNull(stream, "Unable to load resource " + editConfigResourcePath);
+            checkNotNull(stream, "Unable to load resource " + editConfigResourcePath);
 
             Document doc = XmlUtil.readXmlToDocument(stream);
 
@@ -270,7 +277,7 @@ public class ConfigPusher {
     private static NetconfMessage getCommitMessage() {
         String resource = "/netconfOp/commit.xml";
         try (InputStream stream = ConfigPusher.class.getResourceAsStream(resource)) {
-            Preconditions.checkNotNull(stream, "Unable to load resource " + resource);
+            checkNotNull(stream, "Unable to load resource " + resource);
             return new NetconfMessage(XmlUtil.readXmlToDocument(stream));
         } catch (SAXException | IOException e) {
             // error reading the xml file bundled into the jar