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 java.util.Collections;
11 import java.util.HashSet;
12 import java.util.Iterator;
13 import java.util.LinkedList;
15 import java.util.TreeMap;
16 import java.util.TreeSet;
18 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
19 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
20 import org.opendaylight.controller.netconf.api.NetconfSession;
21 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
22 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
23 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
24 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit;
25 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema;
26 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStartExi;
27 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopExi;
28 import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
29 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
30 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
31 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
32 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilterChain;
33 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
34 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.w3c.dom.Document;
39 import com.google.common.base.Preconditions;
40 import com.google.common.collect.Maps;
41 import com.google.common.collect.Sets;
43 public class NetconfOperationRouterImpl implements NetconfOperationRouter {
45 private static final Logger logger = LoggerFactory.getLogger(NetconfOperationRouterImpl.class);
47 private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
49 private final Set<NetconfOperation> allNetconfOperations;
50 private final TreeSet<NetconfOperationFilter> allSortedFilters;
52 private final CapabilityProvider capabilityProvider;
55 public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
56 CapabilityProvider capabilityProvider,
57 DefaultCommitNotificationProducer commitNotifier) {
59 this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
61 this.capabilityProvider = capabilityProvider;
63 Set<NetconfOperation> defaultNetconfOperations = Sets.newHashSet();
64 defaultNetconfOperations.add(new DefaultGetSchema(capabilityProvider, netconfOperationServiceSnapshot
65 .getNetconfSessionIdForReporting()));
66 defaultNetconfOperations.add(new DefaultCloseSession(netconfOperationServiceSnapshot
67 .getNetconfSessionIdForReporting()));
68 defaultNetconfOperations.add(new DefaultStartExi(
69 netconfOperationServiceSnapshot
70 .getNetconfSessionIdForReporting()));
71 defaultNetconfOperations.add(new DefaultStopExi(
72 netconfOperationServiceSnapshot
73 .getNetconfSessionIdForReporting()));
75 allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot);
77 DefaultCommit defaultCommit = new DefaultCommit(commitNotifier, capabilityProvider,
78 netconfOperationServiceSnapshot.getNetconfSessionIdForReporting());
79 Set<NetconfOperationFilter> defaultFilters = Sets.<NetconfOperationFilter> newHashSet(defaultCommit);
80 allSortedFilters = getAllNetconfFilters(defaultFilters, netconfOperationServiceSnapshot);
83 private static Set<NetconfOperation> getAllNetconfOperations(Set<NetconfOperation> defaultNetconfOperations,
84 NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
85 Set<NetconfOperation> result = new HashSet<>();
86 result.addAll(defaultNetconfOperations);
88 for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
89 final Set<NetconfOperation> netOpsFromService = netconfOperationService.getNetconfOperations();
90 for (NetconfOperation netconfOperation : netOpsFromService) {
91 Preconditions.checkState(result.contains(netconfOperation) == false,
92 "Netconf operation %s already present", netconfOperation);
93 result.add(netconfOperation);
96 return Collections.unmodifiableSet(result);
99 private static TreeSet<NetconfOperationFilter> getAllNetconfFilters(Set<NetconfOperationFilter> defaultFilters,
100 NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
101 TreeSet<NetconfOperationFilter> result = new TreeSet<>(defaultFilters);
102 for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
103 final Set<NetconfOperationFilter> filtersFromService = netconfOperationService.getFilters();
104 for (NetconfOperationFilter filter : filtersFromService) {
105 Preconditions.checkState(result.contains(filter) == false, "Filter %s already present", filter);
112 public CapabilityProvider getCapabilityProvider() {
113 return capabilityProvider;
117 public synchronized Document onNetconfMessage(Document message,
118 NetconfSession session) throws NetconfDocumentedException {
119 NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(
121 logger.debug("Forwarding netconf message {} to {}", XmlUtil.toString(message),
122 netconfOperationExecution.operationWithHighestPriority);
124 final LinkedList<NetconfOperationFilterChain> chain = new LinkedList<>();
125 chain.push(netconfOperationExecution);
127 for (Iterator<NetconfOperationFilter> it = allSortedFilters.descendingIterator(); it.hasNext();) {
128 final NetconfOperationFilter filter = it.next();
129 final NetconfOperationFilterChain prevItem = chain.getFirst();
130 NetconfOperationFilterChain currentItem = new NetconfOperationFilterChain() {
132 public Document execute(Document message, NetconfOperationRouter operationRouter)
133 throws NetconfDocumentedException {
134 logger.trace("Entering {}", filter);
135 return filter.doFilter(message, operationRouter, prevItem);
138 chain.push(currentItem);
140 return chain.getFirst().execute(message, this);
143 private NetconfOperationExecution getNetconfOperationWithHighestPriority(
144 Document message, NetconfSession session) {
147 TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(
150 Preconditions.checkState(sortedPriority.isEmpty() == false, "No %s available to handle message %s",
151 NetconfOperation.class.getName(), XmlUtil.toString(message));
153 HandlingPriority highestFoundPriority = sortedPriority.lastKey();
155 int netconfOperationsWithHighestPriority = sortedPriority.get(highestFoundPriority).size();
157 Preconditions.checkState(netconfOperationsWithHighestPriority == 1,
158 "Multiple %s available to handle message %s", NetconfOperation.class.getName(), message);
160 return new NetconfOperationExecution(sortedPriority, highestFoundPriority);
163 private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(
164 Document message, NetconfSession session) {
165 TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = Maps.newTreeMap();
167 for (NetconfOperation netconfOperation : allNetconfOperations) {
168 final HandlingPriority handlingPriority = netconfOperation.canHandle(message);
169 if (netconfOperation instanceof DefaultNetconfOperation) {
170 ((DefaultNetconfOperation) netconfOperation)
171 .setNetconfSession(session);
173 if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
174 Set<NetconfOperation> netconfOperations = sortedPriority.get(handlingPriority);
175 netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations);
176 netconfOperations.add(netconfOperation);
179 return sortedPriority;
182 private Set<NetconfOperation> checkIfNoOperationsOnPriority(
183 TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority, HandlingPriority handlingPriority,
184 Set<NetconfOperation> netconfOperations) {
185 if (netconfOperations == null) {
186 netconfOperations = Sets.newHashSet();
187 sortedPriority.put(handlingPriority, netconfOperations);
189 return netconfOperations;
193 public void close() {
194 netconfOperationServiceSnapshot.close();
197 private class NetconfOperationExecution implements NetconfOperationFilterChain {
198 private final NetconfOperation operationWithHighestPriority;
200 private NetconfOperationExecution(NetconfOperation operationWithHighestPriority) {
201 this.operationWithHighestPriority = operationWithHighestPriority;
204 public NetconfOperationExecution(TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority,
205 HandlingPriority highestFoundPriority) {
206 operationWithHighestPriority = sortedPriority.get(highestFoundPriority).iterator().next();
207 sortedPriority.remove(highestFoundPriority);
211 public Document execute(Document message, NetconfOperationRouter router) throws NetconfDocumentedException {
212 return operationWithHighestPriority.handle(message, router);
217 public String toString() {
218 return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot