Merge "Removing { } from NormalizedNodeJsonBodyWriter"
[controller.git] / opendaylight / netconf / netconf-impl / src / main / java / org / opendaylight / controller / netconf / impl / osgi / NetconfOperationRouterImpl.java
index ff96ad779fbc974539ced455494129381bb09635..9d58bd911c828bfcba3b185b3db20dc9c0d87985 100644 (file)
@@ -8,15 +8,20 @@
 package org.opendaylight.controller.netconf.impl.osgi;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.NavigableMap;
+import java.util.Set;
+import java.util.TreeMap;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
+import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.controller.netconf.impl.CommitNotifier;
 import org.opendaylight.controller.netconf.impl.NetconfServerSession;
-import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit;
-import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultNetconfOperation;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStartExi;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopExi;
@@ -24,108 +29,62 @@ import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceSnapshot;
+import org.opendaylight.controller.netconf.mapping.api.SessionAwareNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.NavigableMap;
-import java.util.Set;
-import java.util.TreeMap;
-
 public class NetconfOperationRouterImpl implements NetconfOperationRouter {
 
-    private static final Logger logger = LoggerFactory.getLogger(NetconfOperationRouterImpl.class);
-
-    private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
-    private Set<NetconfOperation> allNetconfOperations;
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfOperationRouterImpl.class);
+    private final NetconfOperationService netconfOperationServiceSnapshot;
+    private final Collection<NetconfOperation> allNetconfOperations;
 
-    private NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
-        this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
-    }
-
-    private void initNetconfOperations(Set<NetconfOperation> allOperations) {
-        allNetconfOperations = allOperations;
-    }
+    public NetconfOperationRouterImpl(final NetconfOperationService netconfOperationServiceSnapshot,
+                                      final CommitNotifier commitNotifier, final NetconfMonitoringService netconfMonitoringService, final String sessionId) {
+        this.netconfOperationServiceSnapshot = Preconditions.checkNotNull(netconfOperationServiceSnapshot);
 
-    /**
-     * Factory method to produce instance of NetconfOperationRouter
-     */
-    public static NetconfOperationRouter createOperationRouter(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
-                                                               CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
-        NetconfOperationRouterImpl router = new NetconfOperationRouterImpl(netconfOperationServiceSnapshot);
+        final Set<NetconfOperation> ops = new HashSet<>();
+        ops.add(new DefaultCloseSession(sessionId, this));
+        ops.add(new DefaultStartExi(sessionId));
+        ops.add(new DefaultStopExi(sessionId));
+        ops.add(new DefaultCommit(commitNotifier, netconfMonitoringService, sessionId, this));
 
-        Preconditions.checkNotNull(netconfOperationServiceSnapshot);
-        Preconditions.checkNotNull(capabilityProvider);
+        ops.addAll(netconfOperationServiceSnapshot.getNetconfOperations());
 
-        final String sessionId = netconfOperationServiceSnapshot.getNetconfSessionIdForReporting();
-
-        final Set<NetconfOperation> defaultNetconfOperations = Sets.newHashSet();
-        defaultNetconfOperations.add(new DefaultGetSchema(capabilityProvider, sessionId));
-        defaultNetconfOperations.add(new DefaultCloseSession(sessionId, router));
-        defaultNetconfOperations.add(new DefaultStartExi(sessionId));
-        defaultNetconfOperations.add(new DefaultStopExi(sessionId));
-        defaultNetconfOperations.add(new DefaultCommit(commitNotifier, capabilityProvider, sessionId, router));
-
-        router.initNetconfOperations(getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot));
-
-        return router;
-    }
-
-    private static Set<NetconfOperation> getAllNetconfOperations(Set<NetconfOperation> defaultNetconfOperations,
-            NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
-        Set<NetconfOperation> result = new HashSet<>();
-        result.addAll(defaultNetconfOperations);
-
-        for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
-            final Set<NetconfOperation> netOpsFromService = netconfOperationService.getNetconfOperations();
-            for (NetconfOperation netconfOperation : netOpsFromService) {
-                Preconditions.checkState(!result.contains(netconfOperation),
-                        "Netconf operation %s already present", netconfOperation);
-                result.add(netconfOperation);
-            }
-        }
-        return Collections.unmodifiableSet(result);
+        allNetconfOperations = ImmutableSet.copyOf(ops);
     }
 
     @Override
-    public synchronized Document onNetconfMessage(Document message,
-            NetconfServerSession session) throws NetconfDocumentedException {
+    public Document onNetconfMessage(final Document message, final NetconfServerSession session) throws NetconfDocumentedException {
         Preconditions.checkNotNull(allNetconfOperations, "Operation router was not initialized properly");
 
-        NetconfOperationExecution netconfOperationExecution;
-
-        String messageAsString = "";
+        final NetconfOperationExecution netconfOperationExecution;
         try {
-            messageAsString = XmlUtil.toString(message);
             netconfOperationExecution = getNetconfOperationWithHighestPriority(message, session);
         } catch (IllegalArgumentException | IllegalStateException e) {
-            logger.warn("Unable to handle rpc {} on session {}", messageAsString, session, e);
-
-            String errorMessage = String.format("Unable to handle rpc %s on session %s", messageAsString, session);
-            Map<String, String> errorInfo = Maps.newHashMap();
+            final String messageAsString = XmlUtil.toString(message);
+            LOG.warn("Unable to handle rpc {} on session {}", messageAsString, session, e);
 
-            NetconfDocumentedException.ErrorTag tag;
+            final NetconfDocumentedException.ErrorTag tag;
             if (e instanceof IllegalArgumentException) {
-                errorInfo.put(NetconfDocumentedException.ErrorTag.operation_not_supported.toString(), e.getMessage());
                 tag = NetconfDocumentedException.ErrorTag.operation_not_supported;
             } else {
-                errorInfo.put(NetconfDocumentedException.ErrorTag.operation_failed.toString(), e.getMessage());
                 tag = NetconfDocumentedException.ErrorTag.operation_failed;
             }
 
-            throw new NetconfDocumentedException(errorMessage, e, NetconfDocumentedException.ErrorType.application,
-                    tag, NetconfDocumentedException.ErrorSeverity.error, errorInfo);
+            throw new NetconfDocumentedException(
+                String.format("Unable to handle rpc %s on session %s", messageAsString, session),
+                e, NetconfDocumentedException.ErrorType.application,
+                tag, NetconfDocumentedException.ErrorSeverity.error,
+                Collections.singletonMap(tag.toString(), e.getMessage()));
         } catch (RuntimeException e) {
             throw handleUnexpectedEx("Unexpected exception during netconf operation sort", e);
         }
 
         try {
-            return executeOperationWithHighestPriority(message, netconfOperationExecution, messageAsString);
+            return executeOperationWithHighestPriority(message, netconfOperationExecution);
         } catch (RuntimeException e) {
             throw handleUnexpectedEx("Unexpected exception during netconf operation execution", e);
         }
@@ -136,39 +95,41 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         netconfOperationServiceSnapshot.close();
     }
 
-    private NetconfDocumentedException handleUnexpectedEx(String s, Exception e) throws NetconfDocumentedException {
-        logger.error(s, e);
-
-        Map<String, String> info = Maps.newHashMap();
-        info.put(NetconfDocumentedException.ErrorSeverity.error.toString(), e.toString());
+    private static NetconfDocumentedException handleUnexpectedEx(final String s, final Exception e) throws NetconfDocumentedException {
+        LOG.error("{}", s, e);
         return new NetconfDocumentedException("Unexpected error",
                 NetconfDocumentedException.ErrorType.application,
                 NetconfDocumentedException.ErrorTag.operation_failed,
-                NetconfDocumentedException.ErrorSeverity.error, info);
+                NetconfDocumentedException.ErrorSeverity.error,
+                Collections.singletonMap(NetconfDocumentedException.ErrorSeverity.error.toString(), e.toString()));
     }
 
-    private Document executeOperationWithHighestPriority(Document message,
-            NetconfOperationExecution netconfOperationExecution, String messageAsString)
+    private Document executeOperationWithHighestPriority(final Document message,
+            final NetconfOperationExecution netconfOperationExecution)
             throws NetconfDocumentedException {
-        logger.debug("Forwarding netconf message {} to {}", messageAsString, netconfOperationExecution.netconfOperation);
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Forwarding netconf message {} to {}", XmlUtil.toString(message), netconfOperationExecution.netconfOperation);
+        }
+
         return netconfOperationExecution.execute(message);
     }
 
     private NetconfOperationExecution getNetconfOperationWithHighestPriority(
-            Document message, NetconfServerSession session) throws NetconfDocumentedException {
+            final Document message, final NetconfServerSession session) throws NetconfDocumentedException {
 
         NavigableMap<HandlingPriority, NetconfOperation> sortedByPriority = getSortedNetconfOperationsWithCanHandle(
                 message, session);
 
-        Preconditions.checkArgument(sortedByPriority.isEmpty() == false,
-                "No %s available to handle message %s", NetconfOperation.class.getName(),
-                XmlUtil.toString(message));
+        if (sortedByPriority.isEmpty()) {
+            throw new IllegalArgumentException(String.format("No %s available to handle message %s",
+                NetconfOperation.class.getName(), XmlUtil.toString(message)));
+        }
 
         return NetconfOperationExecution.createExecutionChain(sortedByPriority, sortedByPriority.lastKey());
     }
 
-    private TreeMap<HandlingPriority, NetconfOperation> getSortedNetconfOperationsWithCanHandle(Document message,
-            NetconfServerSession session) throws NetconfDocumentedException {
+    private TreeMap<HandlingPriority, NetconfOperation> getSortedNetconfOperationsWithCanHandle(final Document message,
+            final NetconfServerSession session) throws NetconfDocumentedException {
         TreeMap<HandlingPriority, NetconfOperation> sortedPriority = Maps.newTreeMap();
 
         for (NetconfOperation netconfOperation : allNetconfOperations) {
@@ -176,11 +137,14 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
             if (netconfOperation instanceof DefaultNetconfOperation) {
                 ((DefaultNetconfOperation) netconfOperation).setNetconfSession(session);
             }
+            if(netconfOperation instanceof SessionAwareNetconfOperation) {
+                ((SessionAwareNetconfOperation) netconfOperation).setSession(session);
+            }
             if (!handlingPriority.equals(HandlingPriority.CANNOT_HANDLE)) {
 
                 Preconditions.checkState(!sortedPriority.containsKey(handlingPriority),
-                        "Multiple %s available to handle message %s with priority %s",
-                        NetconfOperation.class.getName(), message, handlingPriority);
+                        "Multiple %s available to handle message %s with priority %s, %s and %s",
+                        NetconfOperation.class.getName(), message, handlingPriority, netconfOperation, sortedPriority.get(handlingPriority));
                 sortedPriority.put(handlingPriority, netconfOperation);
             }
         }
@@ -194,7 +158,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         }
 
         @Override
-        public Document execute(Document requestMessage) throws NetconfDocumentedException {
+        public Document execute(final Document requestMessage) throws NetconfDocumentedException {
             throw new NetconfDocumentedException("This execution represents the termination point in operation execution and cannot be executed itself",
                     NetconfDocumentedException.ErrorType.application,
                     NetconfDocumentedException.ErrorTag.operation_failed,
@@ -204,9 +168,9 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
 
     private static class NetconfOperationExecution implements NetconfOperationChainedExecution {
         private final NetconfOperation netconfOperation;
-        private NetconfOperationChainedExecution subsequentExecution;
+        private final NetconfOperationChainedExecution subsequentExecution;
 
-        private NetconfOperationExecution(NetconfOperation netconfOperation, NetconfOperationChainedExecution subsequentExecution) {
+        private NetconfOperationExecution(final NetconfOperation netconfOperation, final NetconfOperationChainedExecution subsequentExecution) {
             this.netconfOperation = netconfOperation;
             this.subsequentExecution = subsequentExecution;
         }
@@ -217,12 +181,12 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         }
 
         @Override
-        public Document execute(Document message) throws NetconfDocumentedException {
+        public Document execute(final Document message) throws NetconfDocumentedException {
             return netconfOperation.handle(message, subsequentExecution);
         }
 
         public static NetconfOperationExecution createExecutionChain(
-                NavigableMap<HandlingPriority, NetconfOperation> sortedByPriority, HandlingPriority handlingPriority) {
+                final NavigableMap<HandlingPriority, NetconfOperation> sortedByPriority, final HandlingPriority handlingPriority) {
             NetconfOperation netconfOperation = sortedByPriority.get(handlingPriority);
             HandlingPriority subsequentHandlingPriority = sortedByPriority.lowerKey(handlingPriority);