From: Maros Marsalek Date: Tue, 4 Mar 2014 10:20:26 +0000 (+0100) Subject: Get rid of netconf operation filters X-Git-Tag: autorelease-tag-v20140601202136_82eb3f9~350^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=d651368d83292f7226a4e91adb55de98036c228f Get rid of netconf operation filters Merge NetconfOperationFilter interface into NetconfOperation Execute all operations that can handle a certain request in chained execution (ordered by priority) Reimplement all current filters as chained operations Remove NetconfOperationRouter parameter from NetconfOperation NetconfOperations handling the same request must have different priorities Change-Id: Iab9c680e6eceab4059feb77616a9d006fb613711 Signed-off-by: Maros Marsalek --- diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/AbstractConfigNetconfOperation.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/AbstractConfigNetconfOperation.java index 6689759ffb..cd99ac4d8d 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/AbstractConfigNetconfOperation.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/AbstractConfigNetconfOperation.java @@ -9,15 +9,9 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations; import org.opendaylight.controller.config.util.ConfigRegistryClient; -import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.api.NetconfOperationRouter; -import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; -import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation; -import org.opendaylight.controller.netconf.util.xml.XmlElement; -import org.w3c.dom.Document; -import org.w3c.dom.Element; +import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; -public abstract class AbstractConfigNetconfOperation extends AbstractNetconfOperation { +public abstract class AbstractConfigNetconfOperation extends AbstractLastNetconfOperation { protected final ConfigRegistryClient configRegistryClient; @@ -26,21 +20,4 @@ public abstract class AbstractConfigNetconfOperation extends AbstractNetconfOper super(netconfSessionIdForReporting); this.configRegistryClient = configRegistryClient; } - - @Override - protected HandlingPriority canHandle(String operationName, String operationNamespace) { - // TODO check namespace - return operationName.equals(getOperationName()) ? HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY - : HandlingPriority.CANNOT_HANDLE; - } - - protected abstract String getOperationName(); - - @Override - protected Element handle(Document document, XmlElement operationElement, NetconfOperationRouter opRouter) - throws NetconfDocumentedException { - return handle(document, operationElement); - } - - protected abstract Element handle(Document document, XmlElement operationElement) throws NetconfDocumentedException; } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java index b3327f54fd..57e356704f 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java @@ -8,6 +8,9 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations; +import java.util.HashMap; +import java.util.Map; + import org.opendaylight.controller.config.api.ConflictingVersionException; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.CommitStatus; @@ -24,9 +27,6 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.util.HashMap; -import java.util.Map; - public class Commit extends AbstractConfigNetconfOperation { private static final Logger logger = LoggerFactory.getLogger(Commit.class); @@ -50,7 +50,7 @@ public class Commit extends AbstractConfigNetconfOperation { } @Override - protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException { + protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { checkXml(xml); CommitStatus status; diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java index 8965deb630..2f72612beb 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java @@ -8,6 +8,9 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations; +import java.util.HashMap; +import java.util.Map; + import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; @@ -21,9 +24,6 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.util.HashMap; -import java.util.Map; - public class DiscardChanges extends AbstractConfigNetconfOperation { public static final String DISCARD = "discard-changes"; @@ -49,7 +49,7 @@ public class DiscardChanges extends AbstractConfigNetconfOperation { } @Override - protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException { + protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { try { fromXml(xml); } catch (final IllegalArgumentException e) { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java index 017b5e6c39..33432e45df 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java @@ -8,7 +8,9 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations; -import com.google.common.base.Preconditions; +import java.util.HashMap; +import java.util.Map; + import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; @@ -23,8 +25,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.util.HashMap; -import java.util.Map; +import com.google.common.base.Preconditions; public class Validate extends AbstractConfigNetconfOperation { @@ -62,7 +63,7 @@ public class Validate extends AbstractConfigNetconfOperation { } @Override - protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException { + protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { try { checkXml(xml); } catch (IllegalStateException e) { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java index bd85f948f5..bb19dc207e 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java @@ -8,10 +8,15 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; + import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.util.ConfigTransactionClient; @@ -40,13 +45,10 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import javax.management.InstanceNotFoundException; -import javax.management.ObjectName; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; public class EditConfig extends AbstractConfigNetconfOperation { @@ -312,7 +314,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { } @Override - protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException { + protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { EditConfigXmlParser.EditConfigExecution editConfigExecution; Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java index dd9a0717b5..73f9ecd6fa 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java @@ -8,7 +8,13 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.get; -import com.google.common.collect.Maps; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.management.ObjectName; + import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot; @@ -35,11 +41,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import javax.management.ObjectName; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import com.google.common.collect.Maps; public class Get extends AbstractConfigNetconfOperation { @@ -119,7 +121,7 @@ public class Get extends AbstractConfigNetconfOperation { } @Override - protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException { + protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { try { checkXml(xml); } catch (final IllegalArgumentException e) { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java index 297f78960b..7cf6e17e9d 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java @@ -8,7 +8,12 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig; -import com.google.common.base.Optional; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import javax.management.ObjectName; + import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.util.ConfigTransactionClient; import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot; @@ -29,10 +34,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import javax.management.ObjectName; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import com.google.common.base.Optional; public class GetConfig extends AbstractConfigNetconfOperation { @@ -101,7 +103,7 @@ public class GetConfig extends AbstractConfigNetconfOperation { } @Override - public Element handle(Document document, XmlElement xml) throws NetconfDocumentedException { + public Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { Datastore source; try { source = fromXml(xml); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java index e7f9772c01..b33eb1d796 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java @@ -8,9 +8,11 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; +import java.util.Map; + +import javax.management.ObjectName; +import javax.management.openmbean.OpenType; + import org.opendaylight.controller.config.util.ConfigRegistryClient; import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; @@ -36,9 +38,9 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import javax.management.ObjectName; -import javax.management.openmbean.OpenType; -import java.util.Map; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; public class RuntimeRpc extends AbstractConfigNetconfOperation { @@ -161,7 +163,7 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { } @Override - protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException { + protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException { // TODO exception handling // TODO check for namespaces and unknown elements diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java index 6eabbe69c6..444500d5dd 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java @@ -8,10 +8,11 @@ package org.opendaylight.controller.netconf.confignetconfconnector.osgi; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + import org.opendaylight.controller.config.api.LookupRegistry; import org.opendaylight.controller.config.util.ConfigRegistryJMXClient; import org.opendaylight.controller.config.yang.store.api.YangStoreException; @@ -22,15 +23,13 @@ import org.opendaylight.controller.netconf.confignetconfconnector.transactions.T import org.opendaylight.controller.netconf.confignetconfconnector.util.Util; import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.yangtools.yang.model.api.Module; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; /** * Manages life cycle of {@link YangStoreSnapshot}. @@ -94,11 +93,6 @@ public class NetconfOperationServiceImpl implements NetconfOperationService { return operationProvider.getOperations(); } - @Override - public Set getFilters() { - return Collections.emptySet(); - } - private static Set setupCapabilities(YangStoreSnapshot yangStoreSnapshot) { Set capabilities = new HashSet<>(); // [RFC6241] 8.3. Candidate Configuration Capability diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java index 0a4f82f057..41d91819a6 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java @@ -8,11 +8,33 @@ package org.opendaylight.controller.netconf.confignetconfconnector; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; +import javax.xml.parsers.ParserConfigurationException; + import org.apache.commons.lang3.StringUtils; import org.junit.Before; import org.junit.Ignore; @@ -52,6 +74,8 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.get import org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc.RuntimeRpc; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; @@ -72,31 +96,11 @@ import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.ObjectName; -import javax.xml.parsers.ParserConfigurationException; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; public class NetconfMappingTest extends AbstractConfigTest { @@ -112,6 +116,8 @@ public class NetconfMappingTest extends AbstractConfigTest { YangStoreSnapshot yangStoreSnapshot; @Mock NetconfOperationRouter netconfOperationRouter; + @Mock + NetconfOperationServiceSnapshot netconfOperationServiceSnapshot; private TransactionProvider transactionProvider; @@ -120,6 +126,7 @@ public class NetconfMappingTest extends AbstractConfigTest { MockitoAnnotations.initMocks(this); doReturn(getMbes()).when(this.yangStoreSnapshot).getModuleMXBeanEntryMap(); doReturn(getModules()).when(this.yangStoreSnapshot).getModules(); + doNothing().when(netconfOperationServiceSnapshot).close(); this.factory = new NetconfTestImplModuleFactory(); this.factory2 = new DepTestImplModuleFactory(); @@ -305,10 +312,10 @@ public class NetconfMappingTest extends AbstractConfigTest { assertEquals(expectedResult, responseFromCandidate); edit("netconfMessages/editConfig_none.xml"); - doNothing().when(netconfOperationRouter).close(); closeSession(); - verify(netconfOperationRouter).close(); + verify(netconfOperationServiceSnapshot).close(); verifyNoMoreInteractions(netconfOperationRouter); + verifyNoMoreInteractions(netconfOperationServiceSnapshot); } private void checkBigDecimal(Element response) { @@ -322,7 +329,7 @@ public class NetconfMappingTest extends AbstractConfigTest { private void closeSession() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException { - DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID); + DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID, netconfOperationServiceSnapshot); executeOp(closeOp, "netconfMessages/closeSession.xml"); } @@ -665,7 +672,7 @@ public class NetconfMappingTest extends AbstractConfigTest { Preconditions.checkState(priority != HandlingPriority.CANNOT_HANDLE); - final Document response = op.handle(request, netconfOperationRouter); + final Document response = op.handle(request, NetconfOperationRouterImpl.EXECUTION_TERMINATION_POINT); logger.debug("Got response\n{}", XmlUtil.toString(response)); return response.getDocumentElement(); } diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/ValidateTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/ValidateTest.java index de1ab71e01..d393121a26 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/ValidateTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/ValidateTest.java @@ -30,7 +30,7 @@ public class ValidateTest { public void test() throws Exception { final XmlElement xml = XmlElement.fromString(""); final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING); - validate.handle(null, xml); + validate.handleWithNoSubsequentOperations(null, xml); } @Test(expected = NetconfDocumentedException.class) @@ -38,14 +38,14 @@ public class ValidateTest { final XmlElement xml = XmlElement.fromString(""); final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING); - validate.handle(null, xml); + validate.handleWithNoSubsequentOperations(null, xml); } @Test(expected = NetconfDocumentedException.class) public void testNoNamespace() throws Exception { final XmlElement xml = XmlElement.fromString(""); final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING); - validate.handle(null, xml); + validate.handleWithNoSubsequentOperations(null, xml); } @Test(expected = NetconfDocumentedException.class) @@ -55,7 +55,7 @@ public class ValidateTest { + XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 + "\">"); final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING); - validate.handle(null, xml); + validate.handleWithNoSubsequentOperations(null, xml); } @Test(expected = NetconfDocumentedException.class) @@ -66,7 +66,7 @@ public class ValidateTest { final TransactionProvider transactionProvider = mock(TransactionProvider.class); doThrow(IllegalStateException.class).when(transactionProvider).validateTransaction(); final Validate validate = new Validate(transactionProvider, null, NETCONF_SESSION_ID_FOR_REPORTING); - validate.handle(null, xml); + validate.handleWithNoSubsequentOperations(null, xml); } @Test(expected = NetconfDocumentedException.class) @@ -77,7 +77,7 @@ public class ValidateTest { final TransactionProvider transactionProvider = mock(TransactionProvider.class); doThrow(ValidationException.class).when(transactionProvider).validateTransaction(); final Validate validate = new Validate(transactionProvider, null, NETCONF_SESSION_ID_FOR_REPORTING); - validate.handle(null, xml); + validate.handleWithNoSubsequentOperations(null, xml); } @Test @@ -89,7 +89,7 @@ public class ValidateTest { final Element okElement = XmlUtil.readXmlToElement(""); doNothing().when(transactionProvider).validateTransaction(); final Validate validate = new Validate(transactionProvider, null, NETCONF_SESSION_ID_FOR_REPORTING); - Element ok = validate.handle(XmlUtil.newDocument(), xml); + Element ok = validate.handleWithNoSubsequentOperations(XmlUtil.newDocument(), xml); assertEquals(XmlUtil.toString(okElement), XmlUtil.toString(ok)); } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java index 460288fe33..f8d9a45c20 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java @@ -12,9 +12,9 @@ import static com.google.common.base.Preconditions.checkState; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.api.NetconfOperationRouter; import org.opendaylight.controller.netconf.api.NetconfSessionListener; import org.opendaylight.controller.netconf.api.NetconfTerminationReason; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl; import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -33,9 +33,9 @@ public class NetconfServerSessionListener implements NetconfSessionListener allNetconfOperations; - private final Set allNetconfOperations; - private final TreeSet allSortedFilters; - - private final CapabilityProvider capabilityProvider; + private NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) { + this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot; + } + private void initNetconfOperations(Set allOperations) { + allNetconfOperations = allOperations; + } - public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot, - CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) { + /** + * Factory method to produce instance of NetconfOperationRouter + */ + public static NetconfOperationRouter createOperationRouter(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot, + CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) { + NetconfOperationRouterImpl router = new NetconfOperationRouterImpl(netconfOperationServiceSnapshot); - this.netconfOperationServiceSnapshot = Preconditions.checkNotNull(netconfOperationServiceSnapshot); - this.capabilityProvider = Preconditions.checkNotNull(capabilityProvider); + Preconditions.checkNotNull(netconfOperationServiceSnapshot); + Preconditions.checkNotNull(capabilityProvider); final String sessionId = netconfOperationServiceSnapshot.getNetconfSessionIdForReporting(); + final Set defaultNetconfOperations = Sets.newHashSet(); defaultNetconfOperations.add(new DefaultGetSchema(capabilityProvider, sessionId)); - defaultNetconfOperations.add(new DefaultCloseSession(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)); - allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot); + router.initNetconfOperations(getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot)); - DefaultCommit defaultCommit = new DefaultCommit(commitNotifier, capabilityProvider, sessionId); - Set defaultFilters = Sets. newHashSet(defaultCommit); - allSortedFilters = getAllNetconfFilters(defaultFilters, netconfOperationServiceSnapshot); + return router; } private static Set getAllNetconfOperations(Set defaultNetconfOperations, @@ -89,29 +92,12 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { return Collections.unmodifiableSet(result); } - private static TreeSet getAllNetconfFilters(Set defaultFilters, - NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) { - TreeSet result = new TreeSet<>(defaultFilters); - for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) { - final Set filtersFromService = netconfOperationService.getFilters(); - for (NetconfOperationFilter filter : filtersFromService) { - Preconditions.checkState(result.contains(filter) == false, - "Filter %s already present, all filters so far: %s", filter, result); - result.add(filter); - } - } - return result; - } - - public CapabilityProvider getCapabilityProvider() { - return capabilityProvider; - } - @Override public synchronized Document onNetconfMessage(Document message, NetconfSession session) throws NetconfDocumentedException { - NetconfOperationExecution netconfOperationExecution; + Preconditions.checkNotNull(allNetconfOperations, "Operation router was not initialized properly"); + NetconfOperationExecution netconfOperationExecution; String messageAsString = XmlUtil.toString(message); try { @@ -144,6 +130,11 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { } } + @Override + public void close() { + netconfOperationServiceSnapshot.close(); + } + private NetconfDocumentedException handleUnexpectedEx(String s, Exception e) throws NetconfDocumentedException { logger.error(s, e); @@ -155,94 +146,91 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { NetconfDocumentedException.ErrorSeverity.error, info); } - private Document executeOperationWithHighestPriority(Document message, NetconfOperationExecution netconfOperationExecution, String messageAsString) throws NetconfDocumentedException { - logger.debug("Forwarding netconf message {} to {}", messageAsString, - netconfOperationExecution.operationWithHighestPriority); - - final LinkedList chain = new LinkedList<>(); - chain.push(netconfOperationExecution); - - for (Iterator it = allSortedFilters.descendingIterator(); it.hasNext();) { - final NetconfOperationFilter filter = it.next(); - final NetconfOperationFilterChain prevItem = chain.getFirst(); - NetconfOperationFilterChain currentItem = new NetconfOperationFilterChain() { - @Override - public Document execute(Document message, NetconfOperationRouter operationRouter) - throws NetconfDocumentedException { - logger.trace("Entering {}", filter); - return filter.doFilter(message, operationRouter, prevItem); - } - }; - chain.push(currentItem); - } - return chain.getFirst().execute(message, this); + private Document executeOperationWithHighestPriority(Document message, + NetconfOperationExecution netconfOperationExecution, String messageAsString) + throws NetconfDocumentedException { + logger.debug("Forwarding netconf message {} to {}", messageAsString, netconfOperationExecution.netconfOperation); + return netconfOperationExecution.execute(message); } private NetconfOperationExecution getNetconfOperationWithHighestPriority( Document message, NetconfSession session) { - TreeMap> sortedPriority = getSortedNetconfOperationsWithCanHandle( + TreeMap sortedByPriority = getSortedNetconfOperationsWithCanHandle( message, session); - Preconditions.checkArgument(sortedPriority.isEmpty() == false, "No %s available to handle message %s", - NetconfOperation.class.getName(), XmlUtil.toString(message)); - - HandlingPriority highestFoundPriority = sortedPriority.lastKey(); - - int netconfOperationsWithHighestPriority = sortedPriority.get(highestFoundPriority).size(); - - Preconditions.checkState(netconfOperationsWithHighestPriority == 1, - "Multiple %s available to handle message %s", NetconfOperation.class.getName(), message); + Preconditions.checkArgument(sortedByPriority.isEmpty() == false, + "No %s available to handleWithNoSubsequentOperations message %s", NetconfOperation.class.getName(), + XmlUtil.toString(message)); - return new NetconfOperationExecution(sortedPriority, highestFoundPriority); + return NetconfOperationExecution.createExecutionChain(sortedByPriority, sortedByPriority.lastKey()); } - private TreeMap> getSortedNetconfOperationsWithCanHandle( - Document message, NetconfSession session) { - TreeMap> sortedPriority = Maps.newTreeMap(); + private TreeMap getSortedNetconfOperationsWithCanHandle(Document message, + NetconfSession session) { + TreeMap sortedPriority = Maps.newTreeMap(); for (NetconfOperation netconfOperation : allNetconfOperations) { final HandlingPriority handlingPriority = netconfOperation.canHandle(message); if (netconfOperation instanceof DefaultNetconfOperation) { - ((DefaultNetconfOperation) netconfOperation) - .setNetconfSession(session); + ((DefaultNetconfOperation) netconfOperation).setNetconfSession(session); } if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) { - Set netconfOperations = sortedPriority.get(handlingPriority); - netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations); - netconfOperations.add(netconfOperation); + + Preconditions.checkState(sortedPriority.containsKey(handlingPriority) == false, + "Multiple %s available to handle message %s with priority %s", + NetconfOperation.class.getName(), message, handlingPriority); + sortedPriority.put(handlingPriority, netconfOperation); } } return sortedPriority; } - private Set checkIfNoOperationsOnPriority( - TreeMap> sortedPriority, HandlingPriority handlingPriority, - Set netconfOperations) { - if (netconfOperations == null) { - netconfOperations = Sets.newHashSet(); - sortedPriority.put(handlingPriority, netconfOperations); + public static final NetconfOperationChainedExecution EXECUTION_TERMINATION_POINT = new NetconfOperationChainedExecution() { + @Override + public boolean isExecutionTermination() { + return true; } - return netconfOperations; - } - @Override - public void close() { - netconfOperationServiceSnapshot.close(); - } + @Override + public Document execute(Document requestMessage) throws NetconfDocumentedException { + throw new IllegalStateException("This execution represents the termination point in operation execution and cannot be executed itself"); + } + }; + + private static class NetconfOperationExecution implements NetconfOperationChainedExecution { + private final NetconfOperation netconfOperation; + private NetconfOperationChainedExecution subsequentExecution; - private class NetconfOperationExecution implements NetconfOperationFilterChain { - private final NetconfOperation operationWithHighestPriority; + private NetconfOperationExecution(NetconfOperation netconfOperation, NetconfOperationChainedExecution subsequentExecution) { + this.netconfOperation = netconfOperation; + this.subsequentExecution = subsequentExecution; + } - public NetconfOperationExecution(TreeMap> sortedPriority, - HandlingPriority highestFoundPriority) { - operationWithHighestPriority = sortedPriority.get(highestFoundPriority).iterator().next(); - sortedPriority.remove(highestFoundPriority); + @Override + public boolean isExecutionTermination() { + return false; } @Override - public Document execute(Document message, NetconfOperationRouter router) throws NetconfDocumentedException { - return operationWithHighestPriority.handle(message, router); + public Document execute(Document message) throws NetconfDocumentedException { + return netconfOperation.handle(message, subsequentExecution); + } + + public static NetconfOperationExecution createExecutionChain( + TreeMap sortedByPriority, HandlingPriority handlingPriority) { + NetconfOperation netconfOperation = sortedByPriority.get(handlingPriority); + HandlingPriority subsequentHandlingPriority = sortedByPriority.lowerKey(handlingPriority); + + NetconfOperationChainedExecution subsequentExecution = null; + + if (subsequentHandlingPriority != null) { + subsequentExecution = createExecutionChain(sortedByPriority, subsequentHandlingPriority); + } else { + subsequentExecution = EXECUTION_TERMINATION_POINT; + } + + return new NetconfOperationExecution(netconfOperation, subsequentExecution); } } @@ -251,7 +239,4 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot + '}'; } - - - } diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java index c0d52ad85e..43854374a0 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java @@ -8,12 +8,26 @@ package org.opendaylight.controller.netconf.impl; -import com.google.common.base.Optional; -import com.google.common.collect.Sets; -import io.netty.channel.ChannelFuture; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.HashedWheelTimer; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import java.io.DataOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.management.ManagementFactory; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import javax.management.ObjectName; + import org.apache.commons.io.IOUtils; import org.junit.After; import org.junit.Before; @@ -26,7 +40,6 @@ import org.opendaylight.controller.config.yang.store.api.YangStoreService; import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; -import org.opendaylight.controller.netconf.api.NetconfOperationRouter; import org.opendaylight.controller.netconf.client.NetconfClient; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; @@ -34,7 +47,7 @@ import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader; @@ -44,24 +57,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; -import javax.management.ObjectName; -import java.io.DataOutputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.management.ManagementFactory; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import com.google.common.base.Optional; +import com.google.common.collect.Sets; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.HashedWheelTimer; public class ConcurrentClientsTest { @@ -151,8 +153,7 @@ public class ConcurrentClientsTest { } @Override - public Document handle(Document message, NetconfOperationRouter operationRouter) - throws NetconfDocumentedException { + public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException { try { return XmlUtil.readXmlToDocument(""); } catch (Exception e) { @@ -162,11 +163,6 @@ public class ConcurrentClientsTest { }); } - @Override - public Set getFilters() { - return Collections.emptySet(); - } - @Override public void close() { } diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/HandlingPriority.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/HandlingPriority.java index 176cf2d28c..1236138e6c 100644 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/HandlingPriority.java +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/HandlingPriority.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.netconf.mapping.api; import com.google.common.base.Optional; +import com.google.common.base.Preconditions; public class HandlingPriority implements Comparable { @@ -33,7 +34,15 @@ public class HandlingPriority implements Comparable { * @return priority number or Optional.absent otherwise */ public Optional getPriority() { - return Optional.of(priority).or(Optional. absent()); + return Optional.fromNullable(priority); + } + + public HandlingPriority increasePriority(int priorityIncrease) { + Preconditions.checkState(priority!=null, "Unable to increase priority for %s", this); + Preconditions.checkArgument(priorityIncrease > 0, "Negative increase"); + Preconditions.checkArgument(Long.valueOf(priority) + priorityIncrease < Integer.MAX_VALUE, + "Resulting priority cannot be higher than %s", Integer.MAX_VALUE); + return getHandlingPriority(priority + priorityIncrease); } @Override diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperation.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperation.java index 58857b4438..b70f8dbd39 100644 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperation.java +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperation.java @@ -9,12 +9,45 @@ package org.opendaylight.controller.netconf.mapping.api; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.api.NetconfOperationRouter; import org.w3c.dom.Document; +/** + * NetconfOperation handles netconf requests. Multiple operations might be + * capable of handling one request at the same time. In such case, these + * operations are chained (ordered by HandlingPriority returned by canHandle + * method) and executed. + * + * Operation can be declared as singleton or last in chain (see abstract + * implementations in netconf-util). If the operation is not singleton or last, + * it is responsible for the execution of subsequent operation and for merging + * the results. + * + */ public interface NetconfOperation { - HandlingPriority canHandle(Document message); + /** + * Singleton operations should return + * HandlingPriority.HANDLE_WITH_MAX_PRIORITY, last operations + * HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY. + * + * @param requestMessage + * @return + */ + HandlingPriority canHandle(Document requestMessage); - Document handle(Document message, NetconfOperationRouter operationRouter) throws NetconfDocumentedException; + /** + * Execute current netconf operation and trigger execution of subsequent + * operations. subsequentOperation parameter will provide information, if + * current operation is the termination point in execution. In case of + * last/singleton operation, subsequentOperation must indicate termination + * point. + * + * @param requestMessage + * @param subsequentOperation + * execution of subsequent netconf operation + * @return + * @throws NetconfDocumentedException + */ + Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) + throws NetconfDocumentedException; } diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationChainedExecution.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationChainedExecution.java new file mode 100644 index 0000000000..2298153017 --- /dev/null +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationChainedExecution.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.netconf.mapping.api; + +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.w3c.dom.Document; + +/** + * Single link in netconf operation execution chain. + * Wraps the execution of a single netconf operation. + */ +public interface NetconfOperationChainedExecution { + + /** + * @return true if this is termination point in operation execution, false + * if there is a subsequent operation present that needs to be + * executed + */ + boolean isExecutionTermination(); + + /** + * Do not execute if this is termination point + */ + Document execute(Document requestMessage) throws NetconfDocumentedException; +} diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java deleted file mode 100644 index c9e04e3dcd..0000000000 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.controller.netconf.mapping.api; - -import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.api.NetconfOperationRouter; -import org.w3c.dom.Document; - -/** - * Filters wrap each netconf operation, if there is one found. Filters are - * sorted and applied from the greatest to smallest sorting order. - */ -public interface NetconfOperationFilter extends Comparable { - - Document doFilter(Document message, NetconfOperationRouter operationRouter, NetconfOperationFilterChain filterChain) - throws NetconfDocumentedException; - - int getSortingOrder(); - -} diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilterChain.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilterChain.java deleted file mode 100644 index 7a0eb9150d..0000000000 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilterChain.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.controller.netconf.mapping.api; - -import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.api.NetconfOperationRouter; -import org.w3c.dom.Document; - -public interface NetconfOperationFilterChain { - - Document execute(Document message, NetconfOperationRouter operationRouter) throws NetconfDocumentedException; - -} diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationService.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationService.java index 858636a389..5e2cba2cba 100644 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationService.java +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationService.java @@ -25,8 +25,6 @@ public interface NetconfOperationService extends AutoCloseable { */ Set getNetconfOperations(); - Set getFilters(); - /** * Called when netconf session is destroyed. */ diff --git a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java index 0b923f6c5a..1b32b52e53 100644 --- a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java +++ b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java @@ -7,12 +7,12 @@ */ package org.opendaylight.controller.netconf.monitoring; -import com.google.common.collect.Maps; +import java.util.Map; + import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.api.NetconfOperationRouter; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilterChain; +import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; import org.opendaylight.controller.netconf.monitoring.xml.JaxBSerializer; import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState; import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation; @@ -24,32 +24,50 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.util.Map; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; -public class Get implements NetconfOperationFilter { +public class Get extends AbstractNetconfOperation { private static final Logger logger = LoggerFactory.getLogger(Get.class); private final NetconfMonitoringService netconfMonitor; public Get(NetconfMonitoringService netconfMonitor) { + super(MonitoringConstants.MODULE_NAME); this.netconfMonitor = netconfMonitor; } - @Override - public Document doFilter(Document message, NetconfOperationRouter operationRouter, - NetconfOperationFilterChain filterChain) throws NetconfDocumentedException { - AbstractNetconfOperation.OperationNameAndNamespace operationNameAndNamespace = new AbstractNetconfOperation.OperationNameAndNamespace( - message); - if (canHandle(operationNameAndNamespace)) { - return handle(message, operationRouter, filterChain); + private Element getPlaceholder(Document innerResult) { + try { + XmlElement rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(), + XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.RFC4741_TARGET_NAMESPACE); + return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement(); + } catch (RuntimeException e) { + throw new IllegalArgumentException(String.format( + "Input xml in wrong format, Expecting root element %s with child element %s, but was %s", + XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.DATA_KEY, + XmlUtil.toString(innerResult.getDocumentElement())), e); } - return filterChain.execute(message, operationRouter); } - private Document handle(Document message, NetconfOperationRouter operationRouter, - NetconfOperationFilterChain filterChain) throws NetconfDocumentedException { + @Override + protected String getOperationName() { + return XmlNetconfConstants.GET; + } + + @Override + protected HandlingPriority getHandlingPriority() { + return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.increasePriority(1); + } + + @Override + public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) + throws NetconfDocumentedException { + Preconditions.checkArgument(subsequentOperation.isExecutionTermination() == false, + "Subsequent netconf operation expected by %s", this); + try { - Document innerResult = filterChain.execute(message, operationRouter); + Document innerResult = subsequentOperation.execute(requestMessage); NetconfState netconfMonitoring = new NetconfState(netconfMonitor); Element monitoringXmlElement = new JaxBSerializer().toXml(netconfMonitoring); @@ -70,35 +88,9 @@ public class Get implements NetconfOperationFilter { } } - private Element getPlaceholder(Document innerResult) { - try { - XmlElement rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(), - XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.RFC4741_TARGET_NAMESPACE); - return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement(); - } catch (RuntimeException e) { - throw new IllegalArgumentException(String.format( - "Input xml in wrong format, Expecting root element %s with child element %s, but was %s", - XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.DATA_KEY, - XmlUtil.toString(innerResult.getDocumentElement())), e); - } - } - - private boolean canHandle(AbstractNetconfOperation.OperationNameAndNamespace operationNameAndNamespace) { - if (operationNameAndNamespace.getOperationName().equals(XmlNetconfConstants.GET) == false) - return false; - return operationNameAndNamespace.getNamespace().equals( - XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); - } - @Override - public int getSortingOrder() { - // FIXME filters for different operations cannot have same order - return 1; + protected Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation) + throws NetconfDocumentedException { + throw new UnsupportedOperationException("Never gets called"); } - - @Override - public int compareTo(NetconfOperationFilter o) { - return Integer.compare(getSortingOrder(), o.getSortingOrder()); - } - } diff --git a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java index fe01847f59..a42bc09591 100644 --- a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java +++ b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java @@ -7,27 +7,26 @@ */ package org.opendaylight.controller.netconf.monitoring.osgi; -import com.google.common.base.Charsets; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; -import com.google.common.io.Files; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; -import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.controller.netconf.monitoring.Get; import org.opendaylight.controller.netconf.monitoring.MonitoringConstants; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas; -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import com.google.common.base.Charsets; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; +import com.google.common.io.Files; public class NetconfMonitoringOperationService implements NetconfOperationService { @@ -89,12 +88,7 @@ public class NetconfMonitoringOperationService implements NetconfOperationServic @Override public Set getNetconfOperations() { - return Collections.emptySet(); - } - - @Override - public Set getFilters() { - return Sets.newHashSet(new Get(monitor)); + return Sets.newHashSet(new Get(monitor)); } @Override diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperation.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperation.java new file mode 100644 index 0000000000..d6d57c50ac --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperation.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.netconf.util.mapping; + +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import com.google.common.base.Preconditions; + +public abstract class AbstractLastNetconfOperation extends AbstractNetconfOperation { + + protected AbstractLastNetconfOperation(String netconfSessionIdForReporting) { + super(netconfSessionIdForReporting); + } + + @Override + protected Element handle(Document document, XmlElement operationElement, + NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException { + Preconditions.checkArgument(subsequentOperation.isExecutionTermination(), + "No netconf operation expected to be subsequent to %s, but is %s", this, subsequentOperation); + + return handleWithNoSubsequentOperations(document, operationElement); + } + + @Override + protected HandlingPriority getHandlingPriority() { + return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY; + } + + protected abstract Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException; +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java index ba6364662c..2e3100f8b2 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java @@ -11,9 +11,9 @@ package org.opendaylight.controller.netconf.util.mapping; import java.util.Map; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.api.NetconfOperationRouter; 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.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -64,19 +64,34 @@ public abstract class AbstractNetconfOperation implements NetconfOperation { XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); } - protected abstract HandlingPriority canHandle(String operationName, String netconfOperationNamespace); + protected HandlingPriority canHandle(String operationName, String operationNamespace) { + return operationName.equals(getOperationName()) && operationNamespace.equals(getOperationNamespace()) + ? getHandlingPriority() + : HandlingPriority.CANNOT_HANDLE; + } + + protected HandlingPriority getHandlingPriority() { + return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY; + } + + protected String getOperationNamespace() { + return XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0; + } + + protected abstract String getOperationName(); @Override - public final Document handle(Document message, NetconfOperationRouter opRouter) throws NetconfDocumentedException { + public Document handle(Document requestMessage, + NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException { - XmlElement requestElement = getRequestElementWithCheck(message); + XmlElement requestElement = getRequestElementWithCheck(requestMessage); Document document = XmlUtil.newDocument(); XmlElement operationElement = requestElement.getOnlyChildElement(); Map attributes = requestElement.getAttributes(); - Element response = handle(document, operationElement, opRouter); + Element response = handle(document, operationElement, subsequentOperation); Element rpcReply = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, XmlNetconfConstants.RPC_REPLY_KEY); @@ -98,11 +113,16 @@ public abstract class AbstractNetconfOperation implements NetconfOperation { return document; } - protected abstract Element handle(Document document, XmlElement operationElement, NetconfOperationRouter opRouter) + protected abstract Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException; @Override public String toString() { - return getClass() + "{" + netconfSessionIdForReporting + '}'; + final StringBuffer sb = new StringBuffer("AbstractConfigNetconfOperation{"); + sb.append("name=").append(getOperationName()); + sb.append(", namespace=").append(getOperationNamespace()); + sb.append(", session=").append(netconfSessionIdForReporting); + sb.append('}'); + return sb.toString(); } } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperation.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperation.java new file mode 100644 index 0000000000..4491e763b3 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperation.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.netconf.util.mapping; + +import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; + +public abstract class AbstractSingletonNetconfOperation extends AbstractLastNetconfOperation { + + protected AbstractSingletonNetconfOperation(String netconfSessionIdForReporting) { + super(netconfSessionIdForReporting); + } + + @Override + protected HandlingPriority getHandlingPriority() { + return HandlingPriority.HANDLE_WITH_MAX_PRIORITY; + } + +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java index 4a6586cd1d..f32179a1e9 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java @@ -38,7 +38,7 @@ public final class XmlNetconfConstants { public static final String PREFIX = "prefix"; // - // + // TODO duplicate public static final String RFC4741_TARGET_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0"; public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0";