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.*;
21 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 import org.w3c.dom.Document;
28 public class NetconfOperationRouterImpl implements NetconfOperationRouter {
30 private static final Logger logger = LoggerFactory.getLogger(NetconfOperationRouterImpl.class);
32 private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
34 private final Set<NetconfOperation> allNetconfOperations;
35 private final TreeSet<NetconfOperationFilter> allSortedFilters;
37 private final CapabilityProvider capabilityProvider;
39 public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
40 CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
42 this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
44 this.capabilityProvider = capabilityProvider;
46 Set<NetconfOperation> defaultNetconfOperations = Sets.newHashSet();
47 defaultNetconfOperations.add(new DefaultGetSchema(capabilityProvider, netconfOperationServiceSnapshot
48 .getNetconfSessionIdForReporting()));
49 defaultNetconfOperations.add(new DefaultCloseSession(netconfOperationServiceSnapshot
50 .getNetconfSessionIdForReporting()));
52 allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot);
54 DefaultCommit defaultCommit = new DefaultCommit(commitNotifier, capabilityProvider,
55 netconfOperationServiceSnapshot.getNetconfSessionIdForReporting());
56 Set<NetconfOperationFilter> defaultFilters = Sets.<NetconfOperationFilter> newHashSet(defaultCommit);
57 allSortedFilters = getAllNetconfFilters(defaultFilters, netconfOperationServiceSnapshot);
60 private static Set<NetconfOperation> getAllNetconfOperations(Set<NetconfOperation> defaultNetconfOperations,
61 NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
62 Set<NetconfOperation> result = new HashSet<>();
63 result.addAll(defaultNetconfOperations);
65 for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
66 final Set<NetconfOperation> netOpsFromService = netconfOperationService.getNetconfOperations();
67 for (NetconfOperation netconfOperation : netOpsFromService) {
68 Preconditions.checkState(result.contains(netconfOperation) == false,
69 "Netconf operation %s already present", netconfOperation);
70 result.add(netconfOperation);
73 return Collections.unmodifiableSet(result);
76 private static TreeSet<NetconfOperationFilter> getAllNetconfFilters(Set<NetconfOperationFilter> defaultFilters,
77 NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
78 TreeSet<NetconfOperationFilter> result = new TreeSet<>(defaultFilters);
79 for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
80 final Set<NetconfOperationFilter> filtersFromService = netconfOperationService.getFilters();
81 for (NetconfOperationFilter filter : filtersFromService) {
82 Preconditions.checkState(result.contains(filter) == false, "Filter %s already present", filter);
89 public CapabilityProvider getCapabilityProvider() {
90 return capabilityProvider;
94 public synchronized Document onNetconfMessage(Document message) throws NetconfDocumentedException {
95 NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(message);
96 logger.debug("Forwarding netconf message {} to {}", XmlUtil.toString(message),
97 netconfOperationExecution.operationWithHighestPriority);
99 final LinkedList<NetconfOperationFilterChain> chain = new LinkedList<>();
100 chain.push(netconfOperationExecution);
102 for (Iterator<NetconfOperationFilter> it = allSortedFilters.descendingIterator(); it.hasNext();) {
103 final NetconfOperationFilter filter = it.next();
104 final NetconfOperationFilterChain prevItem = chain.getFirst();
105 NetconfOperationFilterChain currentItem = new NetconfOperationFilterChain() {
107 public Document execute(Document message, NetconfOperationRouter operationRouter)
108 throws NetconfDocumentedException {
109 logger.trace("Entering {}", filter);
110 return filter.doFilter(message, operationRouter, prevItem);
113 chain.push(currentItem);
115 return chain.getFirst().execute(message, this);
118 private NetconfOperationExecution getNetconfOperationWithHighestPriority(Document message) {
121 TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(message);
123 Preconditions.checkState(sortedPriority.isEmpty() == false, "No %s available to handle message %s",
124 NetconfOperation.class.getName(), XmlUtil.toString(message));
126 HandlingPriority highestFoundPriority = sortedPriority.lastKey();
128 int netconfOperationsWithHighestPriority = sortedPriority.get(highestFoundPriority).size();
130 Preconditions.checkState(netconfOperationsWithHighestPriority == 1,
131 "Multiple %s available to handle message %s", NetconfOperation.class.getName(), message);
133 return new NetconfOperationExecution(sortedPriority, highestFoundPriority);
136 private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(Document message) {
137 TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = Maps.newTreeMap();
139 for (NetconfOperation netconfOperation : allNetconfOperations) {
140 final HandlingPriority handlingPriority = netconfOperation.canHandle(message);
142 if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
143 Set<NetconfOperation> netconfOperations = sortedPriority.get(handlingPriority);
144 netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations);
145 netconfOperations.add(netconfOperation);
148 return sortedPriority;
151 private Set<NetconfOperation> checkIfNoOperationsOnPriority(
152 TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority, HandlingPriority handlingPriority,
153 Set<NetconfOperation> netconfOperations) {
154 if (netconfOperations == null) {
155 netconfOperations = Sets.newHashSet();
156 sortedPriority.put(handlingPriority, netconfOperations);
158 return netconfOperations;
162 public void close() {
163 netconfOperationServiceSnapshot.close();
166 private class NetconfOperationExecution implements NetconfOperationFilterChain {
167 private final NetconfOperation operationWithHighestPriority;
169 private NetconfOperationExecution(NetconfOperation operationWithHighestPriority) {
170 this.operationWithHighestPriority = operationWithHighestPriority;
173 public NetconfOperationExecution(TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority,
174 HandlingPriority highestFoundPriority) {
175 operationWithHighestPriority = sortedPriority.get(highestFoundPriority).iterator().next();
176 sortedPriority.remove(highestFoundPriority);
180 public Document execute(Document message, NetconfOperationRouter router) throws NetconfDocumentedException {
181 return operationWithHighestPriority.handle(message, router);
186 public String toString() {
187 return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot