2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.netconf.impl.osgi;
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.Maps;
12 import com.google.common.collect.Sets;
13 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
14 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
15 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
16 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
17 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
18 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit;
19 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema;
20 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
21 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
22 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
23 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilterChain;
24 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
25 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 import org.w3c.dom.Document;
30 import java.util.Collections;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.LinkedList;
35 import java.util.TreeMap;
36 import java.util.TreeSet;
38 public class NetconfOperationRouterImpl implements NetconfOperationRouter {
40 private static final Logger logger = LoggerFactory.getLogger(NetconfOperationRouterImpl.class);
42 private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
44 private final Set<NetconfOperation> allNetconfOperations;
45 private final TreeSet<NetconfOperationFilter> allSortedFilters;
47 private final CapabilityProvider capabilityProvider;
49 public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
50 CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
52 this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
54 this.capabilityProvider = capabilityProvider;
56 Set<NetconfOperation> defaultNetconfOperations = Sets.newHashSet();
57 defaultNetconfOperations.add(new DefaultGetSchema(capabilityProvider, netconfOperationServiceSnapshot
58 .getNetconfSessionIdForReporting()));
59 defaultNetconfOperations.add(new DefaultCloseSession(netconfOperationServiceSnapshot
60 .getNetconfSessionIdForReporting()));
62 allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot);
64 DefaultCommit defaultCommit = new DefaultCommit(commitNotifier, capabilityProvider,
65 netconfOperationServiceSnapshot.getNetconfSessionIdForReporting());
66 Set<NetconfOperationFilter> defaultFilters = Sets.<NetconfOperationFilter> newHashSet(defaultCommit);
67 allSortedFilters = getAllNetconfFilters(defaultFilters, netconfOperationServiceSnapshot);
70 private static Set<NetconfOperation> getAllNetconfOperations(Set<NetconfOperation> defaultNetconfOperations,
71 NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
72 Set<NetconfOperation> result = new HashSet<>();
73 result.addAll(defaultNetconfOperations);
75 for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
76 final Set<NetconfOperation> netOpsFromService = netconfOperationService.getNetconfOperations();
77 for (NetconfOperation netconfOperation : netOpsFromService) {
78 Preconditions.checkState(result.contains(netconfOperation) == false,
79 "Netconf operation %s already present", netconfOperation);
80 result.add(netconfOperation);
83 return Collections.unmodifiableSet(result);
86 private static TreeSet<NetconfOperationFilter> getAllNetconfFilters(Set<NetconfOperationFilter> defaultFilters,
87 NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
88 TreeSet<NetconfOperationFilter> result = new TreeSet<>(defaultFilters);
89 for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
90 final Set<NetconfOperationFilter> filtersFromService = netconfOperationService.getFilters();
91 for (NetconfOperationFilter filter : filtersFromService) {
92 Preconditions.checkState(result.contains(filter) == false, "Filter %s already present", filter);
99 public CapabilityProvider getCapabilityProvider() {
100 return capabilityProvider;
104 public synchronized Document onNetconfMessage(Document message) throws NetconfDocumentedException {
105 NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(message);
106 logger.debug("Forwarding netconf message {} to {}", XmlUtil.toString(message),
107 netconfOperationExecution.operationWithHighestPriority);
109 final LinkedList<NetconfOperationFilterChain> chain = new LinkedList<>();
110 chain.push(netconfOperationExecution);
112 for (Iterator<NetconfOperationFilter> it = allSortedFilters.descendingIterator(); it.hasNext();) {
113 final NetconfOperationFilter filter = it.next();
114 final NetconfOperationFilterChain prevItem = chain.getFirst();
115 NetconfOperationFilterChain currentItem = new NetconfOperationFilterChain() {
117 public Document execute(Document message, NetconfOperationRouter operationRouter)
118 throws NetconfDocumentedException {
119 logger.trace("Entering {}", filter);
120 return filter.doFilter(message, operationRouter, prevItem);
123 chain.push(currentItem);
125 return chain.getFirst().execute(message, this);
128 private NetconfOperationExecution getNetconfOperationWithHighestPriority(Document message) {
131 TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(message);
133 Preconditions.checkState(sortedPriority.isEmpty() == false, "No %s available to handle message %s",
134 NetconfOperation.class.getName(), XmlUtil.toString(message));
136 HandlingPriority highestFoundPriority = sortedPriority.lastKey();
138 int netconfOperationsWithHighestPriority = sortedPriority.get(highestFoundPriority).size();
140 Preconditions.checkState(netconfOperationsWithHighestPriority == 1,
141 "Multiple %s available to handle message %s", NetconfOperation.class.getName(), message);
143 return new NetconfOperationExecution(sortedPriority, highestFoundPriority);
146 private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(Document message) {
147 TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = Maps.newTreeMap();
149 for (NetconfOperation netconfOperation : allNetconfOperations) {
150 final HandlingPriority handlingPriority = netconfOperation.canHandle(message);
152 if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
153 Set<NetconfOperation> netconfOperations = sortedPriority.get(handlingPriority);
154 netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations);
155 netconfOperations.add(netconfOperation);
158 return sortedPriority;
161 private Set<NetconfOperation> checkIfNoOperationsOnPriority(
162 TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority, HandlingPriority handlingPriority,
163 Set<NetconfOperation> netconfOperations) {
164 if (netconfOperations == null) {
165 netconfOperations = Sets.newHashSet();
166 sortedPriority.put(handlingPriority, netconfOperations);
168 return netconfOperations;
172 public void close() {
173 netconfOperationServiceSnapshot.close();
176 private class NetconfOperationExecution implements NetconfOperationFilterChain {
177 private final NetconfOperation operationWithHighestPriority;
179 private NetconfOperationExecution(NetconfOperation operationWithHighestPriority) {
180 this.operationWithHighestPriority = operationWithHighestPriority;
183 public NetconfOperationExecution(TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority,
184 HandlingPriority highestFoundPriority) {
185 operationWithHighestPriority = sortedPriority.get(highestFoundPriority).iterator().next();
186 sortedPriority.remove(highestFoundPriority);
190 public Document execute(Document message, NetconfOperationRouter router) throws NetconfDocumentedException {
191 return operationWithHighestPriority.handle(message, router);
196 public String toString() {
197 return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot